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()andtranslateEscapes()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.