Record Patterns in switch

OOP · lesson 34 of 43 · 4 min read

Take records apart inside a switch, filter an arm with when, and let the compiler prove the coverage.

Open this lesson in the learning hub

Key points

  • A type pattern binds the whole value; a record pattern binds its parts: case Circle(Point c, int r).
  • Patterns nest, so one arm can reach two levels down: case Circle(Point(var x, var y), int r).
  • A guard filters an arm with when, and a guarded arm has to be written above the plain one it narrows.
  • Over a sealed type the compiler checks every permitted case is covered, so no default arm is needed.
  • Write case null when null is possible; without it a pattern switch still throws NullPointerException.
  • This replaces the instanceof ladder for reading data. It does not replace polymorphism for behaviour you own.

Example

public class Main {

    sealed interface Shape permits Circle, Rect { }

    record Point(int x, int y) { }
    record Circle(Point centre, int r) implements Shape { }
    record Rect(Point topLeft, Point bottomRight) implements Shape { }

    // Arms are tried top to bottom, and each one takes the value apart as it matches.
    static String describe(Shape s) {
        return switch (s) {
            case Circle(Point(var x, var y), int r) when r == 0 -> "a dot at " + x + "," + y;
            case Circle(Point c, int r) -> "circle r=" + r + " at " + c.x() + "," + c.y();
            case Rect(Point tl, Point br) when tl.equals(br) -> "an empty rect";
            case Rect(Point(var x1, var y1), Point(var x2, var y2)) ->
                    "rect " + (x2 - x1) + " by " + (y2 - y1);
        };
    }

    public static void main(String[] args) {
        System.out.println(describe(new Circle(new Point(2, 3), 0)));
        System.out.println(describe(new Circle(new Point(0, 0), 5)));
        System.out.println(describe(new Rect(new Point(1, 1), new Point(1, 1))));
        System.out.println(describe(new Rect(new Point(0, 0), new Point(4, 3))));
        // No default branch: Shape is sealed, so the compiler knows the list is closed.
    }
}

Let the switch take the value apart, and let a sealed type prove you covered it.

This is a reading copy. The full lesson — with the visual explainer, the interactive lab and a Run button for the code — lives in the OOP course, and every lesson in it is listed on the OOP contents page.