Careeroza
Record Patterns
Deconstructing Records (Java 21)
A record pattern takes a record apart into its components right in instanceof or case, and patterns can be nested.
Example
An expression evaluator — the classic use case for sealed interfaces + record patterns.
public class Main {
static int eval(Expr e) {
return switch (e) {
case Num(int value) -> value;
case Add(Expr left, Expr right) -> eval(left) + eval(right);
case Mul(Num(int a), Num(int b)) -> a * b; // nested pattern: fast path
case Mul(Expr left, Expr right) -> eval(left) * eval(right);
};
}
static String show(Expr e) {
return switch (e) {
case Num(var v) -> String.valueOf(v);
case Add(var l, var r) -> "(" + show(l) + " + " + show(r) + ")";
case Mul(var l, var r) -> show(l) + " * " + show(r);
};
}
public static void main(String[] args) {
Expr e = new Add(new Num(2), new Mul(new Num(3), new Num(4)));
System.out.println(show(e) + " = " + eval(e));
Object point = new Point(3, 4);
if (point instanceof Point(int x, int y) && x > 0) {
System.out.println("x=" + x + ", y=" + y + ", distance^2=" + (x * x + y * y));
}
}
}
sealed interface Expr permits Num, Add, Mul {}
record Num(int value) implements Expr {}
record Add(Expr left, Expr right) implements Expr {}
record Mul(Expr left, Expr right) implements Expr {}
record Point(int x, int y) {}Output
(2 + 3 * 4) = 14 x=3, y=4, distance^2=25
Feature Timeline
| Version | Feature |
|---|---|
| Java 10 | var |
| Java 14 | switch expressions, helpful NullPointerException messages |
| Java 15 | text blocks |
| Java 16 | records, pattern matching for instanceof, Stream.toList() |
| Java 17 (LTS) | sealed classes |
| Java 21 (LTS) | pattern matching for switch, record patterns, virtual threads, sequenced collections |
| Java 22+ | unnamed variables _, statements before super(), stream gatherers, module imports |