← Back to Advanced Java Course | Chapter 4: Modern Java Features | Lesson 12 of 12

Java Record Patterns

Record patterns, finalized in Java 21, deconstruct a record's components directly inside instanceof or switch, and can nest, use var, and combine with sealed interfaces for exhaustive matching.

What are Record Patterns?

Record patterns, finalized in Java 21, let a record be deconstructed directly inside an instanceof or switch, extracting its components into named variables in the same expression instead of calling each accessor method separately.

Example: What are Record Patterns?

java
public class Main {
	record Point(int x, int y) {}
	public static void main(String[] args) {
		Object obj = new Point(3, 4);
		if (obj instanceof Point(int x, int y)) { // deconstructed in the same expression
			System.out.println(x + "," + y);
		}
	}
}

Basic Record Deconstruction

Deconstructed components like x and y from a Point are immediately usable as normal local variables within the same condition, including in further boolean expressions combined with the pattern check.

Example: Basic Record Deconstruction

java
public class Main {
	record Point(int x, int y) {}
	public static void main(String[] args) {
		Object obj = new Point(5, 10);
		if (obj instanceof Point(int x, int y) && x > 0) { // usable in further conditions
			System.out.println("Positive x: " + x);
		}
	}
}

Nested Record Patterns

Record patterns can nest, deconstructing a record that itself contains other records in a single pattern, reaching directly into deeply nested structures without a chain of manual accessor calls.

Example: Nested Record Patterns

java
public class Main {
	record Point(int x, int y) {}
	record Line(Point start, Point end) {}
	public static void main(String[] args) {
		Object obj = new Line(new Point(0, 0), new Point(5, 5));
		if (obj instanceof Line(Point(int x1, int y1), Point(int x2, int y2))) { // nested deconstruction
			System.out.println(x1 + "," + y1 + " -> " + x2 + "," + y2);
		}
	}
}

Record Patterns with var

The var keyword can be used in place of an explicit type for any component in a record pattern, letting the compiler infer the type from the record's own definition and keeping the pattern shorter.

Example: Record Patterns with var

java
public class Main {
	record Point(int x, int y) {}
	public static void main(String[] args) {
		Object obj = new Point(7, 8);
		if (obj instanceof Point(var x, var y)) { // type inferred from the record definition
			System.out.println(x + "," + y);
		}
	}
}

Record Patterns in Switch

Record patterns work especially well combined with switch expressions over a sealed hierarchy, deconstructing each possible record type in its own case branch, and a when clause can add extra guard conditions to a specific case.

Example: Record Patterns in Switch

java
public class Main {
	sealed interface Shape permits Circle, Square {}
	record Circle(double radius) implements Shape {}
	record Square(double side) implements Shape {}
	static String describe(Shape s) {
		return switch (s) {
			case Circle(double r) when r > 10 -> "Big circle";
			case Circle(double r) -> "Circle r=" + r;
			case Square(double side) -> "Square side=" + side;
		};
	}
	public static void main(String[] args) {
		System.out.println(describe(new Circle(5)));
	}
}

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.