Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

A record pattern is a declarative language construct that enables the automatic deconstruction of a record instance into its constituent components during pattern matching. Finalized in Java 21 (JEP 440), it extends instanceof operators and switch expressions/statements by binding a record’s internal state directly to local pattern variables, eliminating the need for explicit casting and accessor method invocations.

Syntax Structure

A record pattern consists of a record class type followed by a parenthesized list of pattern variables (or nested patterns) that correspond positionally to the record’s components.
RecordType(ComponentType1 var1, ComponentType2 var2, ...)
Given the following record definitions:
public record Point(int x, int y) {}
public record ColoredPoint(Point p, String color) {}

Deconstruction with instanceof

When a target object matches the specified record type, the JVM automatically invokes the record’s component accessors and initializes the declared pattern variables. These variables are scoped to the block where the pattern match is true.
Object obj = new Point(10, 20);

// The record pattern Point(int x, int y) tests the type and extracts the state
if (obj instanceof Point(int x, int y)) {
    // 'x' and 'y' are local pattern variables initialized with obj.x() and obj.y()
    System.out.println("X: " + x + ", Y: " + y); 
}

Deconstruction in switch

Record patterns integrate directly into switch expressions and statements, allowing for exhaustive type-checking and component extraction across multiple branches.
Object obj = new Point(5, 15);

String description = switch (obj) {
    case Point(int x, int y) -> "Point coordinates: " + x + ", " + y;
    case ColoredPoint(Point p, String c) -> "Colored point: " + c;
    default -> "Unknown object";
};

Nested Record Patterns

Record patterns can be nested to deconstruct complex, hierarchical object graphs in a single operation. The outer pattern matches the primary record, while inner patterns recursively match and extract components of nested records.
Object obj = new ColoredPoint(new Point(10, 20), "RED");

// Deconstructs ColoredPoint, and simultaneously deconstructs its nested Point
if (obj instanceof ColoredPoint(Point(int x, int y), String color)) {
    // 'x', 'y', and 'color' are extracted directly into the current scope
    System.out.println("Color: " + color + " at X: " + x + ", Y: " + y);
}

Type Inference with var

To reduce verbosity, the compiler can infer the types of the pattern variables based on the record’s canonical constructor signature. You can substitute explicit component types with the var identifier.
Object obj = new Point(10, 20);

// The compiler infers 'x' and 'y' as 'int' based on the Point record definition
if (obj instanceof Point(var x, var y)) {
    System.out.println(x + y);
}

Nullability Mechanics

Target Object Nullability When evaluating a record pattern, the behavior with a null target object depends on the context:
  • instanceof: If the target object is null, the pattern match evaluates to false gracefully without throwing a NullPointerException.
  • switch: If the switch selector object is null, the switch statement or expression will throw a NullPointerException unless an explicit case null is provided.
Component Nullability If the target object is non-null but its nested components are null, the success of the match depends entirely on how the component patterns are declared:
  • var Patterns: If the component pattern uses var, the match succeeds, and the corresponding pattern variable is assigned null.
  • Explicit Type and Nested Record Patterns: If the component pattern specifies an explicit type (e.g., Point p) or a nested record pattern (e.g., Point(int x, int y)), it acts as an implicit instanceof check. Because null is not an instance of any type, the match fails.
ColoredPoint cp = new ColoredPoint(null, "BLUE");

// Match SUCCEEDS: 'var' accepts null. 'p' is assigned null, 'c' is assigned "BLUE".
if (cp instanceof ColoredPoint(var p, var c)) {
    System.out.println("Matched with var");
}

// Match FAILS: 'null' is not an instance of Point.
if (cp instanceof ColoredPoint(Point p, String c)) {
    System.out.println("Will not execute");
}

// Match FAILS: Cannot deconstruct a null Point.
if (cp instanceof ColoredPoint(Point(int x, int y), String c)) {
    System.out.println("Will not execute");
}
Master Java with Deep Grasping Methodology!Learn More