Java 23 Pattern Matching: Rewriting Legacy Code with Modern Syntax

Java 23 Pattern Matching: Rewriting Legacy Code with Modern Syntax

Java's pattern matching has evolved from a simple instanceof check to a complete algebraic data type system. Java 23 brings unnamed patterns and primitive patterns that complete the picture.

From instanceof Chains to Sealed Hierarchies

// Before: fragile instanceof chains
if (shape instanceof Circle c) {
    return Math.PI * c.radius() * c.radius();
} else if (shape instanceof Rectangle r) {
    return r.width() * r.height();
}

// After: exhaustive switch with sealed types
sealed interface Shape permits Circle, Rectangle, Triangle {}
record Circle(double radius) implements Shape {}
record Rectangle(double width, double height) implements Shape {}
record Triangle(double base, double height) implements Shape {}

double area(Shape shape) {
    return switch (shape) {
        case Circle(var r) -> Math.PI * r * r;
        case Rectangle(var w, var h) -> w * h;
        case Triangle(var b, var h) -> 0.5 * b * h;
    };
}

Nested Record Patterns

Deconstruct deeply nested structures in a single pattern:

record Address(String city, String country) {}
record Customer(String name, Address address) {}

String greeting(Customer c) {
    return switch (c) {
        case Customer(var n, Address(_, "India")) -> "Namaste, " + n;
        case Customer(var n, Address(_, "Japan")) -> "Konnichiwa, " + n;
        case Customer(var n, _) -> "Hello, " + n;
    };
}

Pattern matching makes Java code more concise, type-safe, and expressive — three things Java was rarely accused of being.

Scroll to Top