Skip to content

Java 15

Neelu edited this page Jul 26, 2026 · 1 revision

☕ Java 15: Text Blocks Standardized & Sealed Classes Preview

Release Date: September 15, 2020 | Type: Standard (non-LTS) | Status: ⚠️ End of Life


📋 Table of Contents

  1. Overview
  2. Core Features
  3. Best Practices

🎯 Overview

Java 15 finalizes text blocks and previews sealed classes — a feature that, combined with records and pattern matching, forms the backbone of modern Java's approach to algebraic data types.

flowchart LR
    A[Text Blocks] -->|Standardized| B["No longer needs\n--enable-preview"]
    C[Sealed Classes] -->|Preview JEP 360| D["Restrict which classes\ncan extend/implement"]
    E[Records + Pattern Matching] -.->|Preview since Java 14| F["Foundation for\nJava 21 pattern matching"]
Loading

🚀 Core Features

1️⃣ Text Blocks (Standard)

// No longer preview — use freely
String query = """
    SELECT *
    FROM users
    WHERE active = true
    """;

// New escape sequences added at standardization:
String noNewline = """
    This is one \
    long line without a break""";   // \ suppresses the line break

String preserveTrailingSpace = """
    trailing space -->  \s
    """;   // \s forces a trailing space that would otherwise be stripped

2️⃣ Sealed Classes (Preview)

What: Restrict exactly which classes/interfaces are allowed to extend or implement a type — a middle ground between final (nobody can extend) and open inheritance (anybody can extend).

public sealed interface Shape
    permits Circle, Square, Triangle {
}

public final class Circle implements Shape {
    private final double radius;
    public Circle(double radius) { this.radius = radius; }
    public double radius() { return radius; }
}

public final class Square implements Shape {
    private final double side;
    public Square(double side) { this.side = side; }
    public double side() { return side; }
}

// Subclasses of a sealed type must be final, sealed, or non-sealed
public non-sealed class Triangle implements Shape {
    // "non-sealed" reopens the hierarchy — anyone can now extend Triangle
}
classDiagram
    class Shape {
        <<sealed interface>>
        permits Circle, Square, Triangle
    }
    class Circle {
        <<final>>
        double radius
    }
    class Square {
        <<final>>
        double side
    }
    class Triangle {
        <<non-sealed>>
    }
    Shape <|.. Circle
    Shape <|.. Square
    Shape <|.. Triangle
Loading

Why it matters: The compiler now knows the complete set of subtypes. Combined with switch pattern matching (Java 21), this enables exhaustive checks without a default branch:

// Preview of what this unlocks in Java 21+ (not valid syntax yet in 15)
double area = switch (shape) {
    case Circle c -> Math.PI * c.radius() * c.radius();
    case Square s -> s.side() * s.side();
    case Triangle t -> 0.5 * t.base() * t.height();
    // no default needed — compiler verifies all permitted types are covered
};

3️⃣ Hidden Classes

What: Classes that cannot be used directly by the bytecode of other classes and are meant to be generated dynamically at runtime — primarily for framework/library authors (used internally by lambdas' LambdaMetafactory and dynamic proxy generation).

// Not typically used directly in application code —
// this is what frameworks like Spring, Hibernate, and the JDK itself
// use internally to generate proxy/lambda classes at runtime
// without polluting the classpath or triggering classloader leaks.

4️⃣ ZGC & Shenandoah — Production Ready

Both low-latency garbage collectors (previously experimental) are now production-ready.

# ZGC — sub-millisecond pause times, scales to multi-terabyte heaps
java -XX:+UseZGC -Xmx16g -jar app.jar

# Shenandoah — similar goals, different algorithm (Red Hat)
java -XX:+UseShenandoahGC -jar app.jar
flowchart TD
    A["Choose GC based on workload"] --> B{"Latency-sensitive?"}
    B -->|Yes, huge heap| C[ZGC]
    B -->|Yes, want mature option| D[Shenandoah]
    B -->|Throughput over latency| E[G1 - default]
    B -->|Batch jobs, short-lived JVM| F[Parallel GC]
Loading

5️⃣ Removed: Nashorn JavaScript Engine

The embedded JS engine is removed (deprecated since Java 11). Use GraalVM's JavaScript engine if you still need to run JS from Java.


💡 Best Practices

✅ Start modeling closed type hierarchies (state machines, AST nodes, API result types) with sealed interfaces
✅ Use text block escape sequences (\, \s) to fine-tune formatting instead of falling back to concatenation
❌ Don't sprinkle sealed everywhere — it's most valuable for types where you genuinely want to enumerate every possible subtype (e.g., a PaymentResult that's Success, Declined, or Pending — nothing else)


Clone this wiki locally