Skip to main content
Advertisement

12.8 Modern Java Syntax (Java 15~21)

Modern language features added from Java 15 to Java 21 make code more concise and expressive.

1. Text Blocks (Java 15+)

Use triple quotes """ to write multi-line strings as-is. Revolutionary for JSON, HTML, SQL, and XML.

// ❌ Old style - complex escaping
String json1 = "{\n" +
" \"name\": \"Alice\",\n" +
" \"age\": 30\n" +
"}";

// ✅ Text Block (Java 15+)
String json2 = """
{
"name": "Alice",
"age": 30
}
""";

// Text Block + formatted
String name = "Alice";
int age = 30;
String html = """
<div class="profile">
<h1>%s</h1>
<p>Age: %d</p>
</div>
""".formatted(name, age);

String sql = """
SELECT *
FROM users
WHERE name = '%s'
AND age >= %d
ORDER BY created_at DESC
""".formatted(name, age);

Indentation Rules

The common indentation is automatically removed. The position of the closing """ determines the indentation baseline.

String aligned = """
Hello
World
"""; // → "Hello\nWorld\n"

// Line continuation with \
String longLine = """
This is \
one line.
"""; // → "This is one line.\n"

2. Record (Java 16+) Advanced Usage

// Compact Constructor with validation
record Range(int min, int max) {
Range { // Compact Constructor
if (min > max)
throw new IllegalArgumentException("min must be <= max: " + min + " > " + max);
}

int size() { return max - min; }
boolean contains(int value) { return value >= min && value <= max; }
}

Range r = new Range(1, 10);
System.out.println(r.size()); // 9
System.out.println(r.contains(5)); // true

// Record + interface
interface Printable { void print(); }
record Point(int x, int y) implements Printable {
@Override public void print() { System.out.printf("Point(%d, %d)%n", x, y); }
}
new Point(3, 4).print(); // Point(3, 4)

3. Pattern Matching (Java 16~21)

instanceof Pattern Matching (Java 16+)

Object obj = "Hello, Java!";

// Old style
if (obj instanceof String) {
String s = (String) obj;
System.out.println(s.length());
}

// Java 16+: check + cast + variable in one step
if (obj instanceof String s) {
System.out.println(s.length());
}

// With condition
if (obj instanceof String s && s.length() > 5) {
System.out.println("Long string: " + s);
}

Switch Pattern Matching (Java 21)

sealed interface Shape permits Circle, Rectangle, Triangle {}
record Circle(double radius) implements Shape {}
record Rectangle(double width, double height) implements Shape {}
record Triangle(double base, double height) implements Shape {}

static String describeShape(Shape shape) {
return switch (shape) {
case Circle c when c.radius() > 100 -> "Giant circle (r=" + c.radius() + ")";
case Circle c -> "Circle (r=" + c.radius() + ")";
case Rectangle r when r.width() == r.height() -> "Square (side=" + r.width() + ")";
case Rectangle r -> "Rectangle (" + r.width() + "×" + r.height() + ")";
case Triangle t -> "Triangle";
};
}

Record Patterns (Java 21)

Destructure record components directly in switch.

record Point(int x, int y) {}
record Line(Point start, Point end) {}

Object obj = new Line(new Point(1, 2), new Point(5, 6));

if (obj instanceof Line(Point(var x1, var y1), Point(var x2, var y2))) {
System.out.printf("Line: (%d,%d) → (%d,%d)%n", x1, y1, x2, y2);
}

4. Sequenced Collections (Java 21)

Consistent access to first and last elements across collection types.

List<String> list = new ArrayList<>(List.of("A", "B", "C", "D"));

System.out.println(list.getFirst()); // "A"
System.out.println(list.getLast()); // "D"

list.addFirst("Z");
list.addLast("X");

List<String> reversed = list.reversed(); // Reverse view (not a new list)
System.out.println(reversed); // [X, D, C, B, A, Z]

// Also works for SequencedMap
LinkedHashMap<String, Integer> map = new LinkedHashMap<>();
map.put("A", 1); map.put("B", 2); map.put("C", 3);
System.out.println(map.firstEntry()); // A=1
System.out.println(map.lastEntry()); // C=3

Pro Tip

Text Block tips:

  • Ideal for JSON mock data, SQL queries, HTML email templates
  • Use \ line continuation for long lines without newlines
  • stripIndent() and translateEscapes() for programmatic text processing

Pattern matching in practice: Replacing complex instanceof + casting chains with switch patterns makes code far more readable. The sealed interface + switch pattern combination gives compile-time exhaustiveness checking.

Advertisement