Modern Java

36. Record Deconstruction Patterns

Record deconstruction patterns let you unpack record components directly in instanceof checks and switch cases — including nested records — providing concise structural decomposition.

Java 21+ (standard)

Explanation

Record deconstruction (JEP 440, Java 21 standard) allows instanceof patterns and switch cases to bind record components: case Point(int x, int y) -> extracts x and y without explicit accessor calls.

Nested deconstruction: case Outer(Inner(int value)) -> unpacks multiple levels in one pattern. This is especially powerful for ADT expression trees, JSON nodes, or any hierarchical record structure.

Deconstruction patterns can be used in instanceof: if (obj instanceof Circle(double r)). The binding variable scope follows the same rules as any pattern — available only where the match is guaranteed.

Example

public class DeconstructionPatterns {
    record Point(double x, double y) {}
    record Line(Point start, Point end) {}
    record Circle(Point centre, double radius) {}

    sealed interface Shape permits Circle, Line {}
    // Reuse Circle and Line

    static String describe(Object obj) {
        return switch (obj) {
            // Flat deconstruction
            case Point(var x, var y) -> String.format("Point at (%.1f, %.1f)", x, y);

            // Nested deconstruction
            case Line(Point(var x1, var y1), Point(var x2, var y2)) ->
                String.format("Line from (%.1f,%.1f) to (%.1f,%.1f)", x1, y1, x2, y2);

            case Circle(Point(var cx, var cy), var r) ->
                String.format("Circle at (%.1f,%.1f) r=%.1f", cx, cy, r);

            default -> "unknown";
        };
    }

    // Deconstruction in instanceof
    static void processPoint(Object obj) {
        if (obj instanceof Point(double x, double y) && x > 0 && y > 0) {
            System.out.println("First quadrant: (" + x + ", " + y + ")");
        }
    }

    public static void main(String[] args) {
        System.out.println(describe(new Point(1.0, 2.0)));
        System.out.println(describe(new Line(new Point(0, 0), new Point(3, 4))));
        System.out.println(describe(new Circle(new Point(5, 5), 10)));

        processPoint(new Point(3.0, 4.0));
        processPoint(new Point(-1.0, 2.0)); // no output — fails guard
    }
}

Sources