• Pattern Matching with Record Patterns

    and Paris Monuments

    In Java, record patterns allow you to check if an object is an instance of a record, and if so, automatically extract its component values for further use. This is especially useful when you work with structured data.

    🔵 For more background, you can refer to JEP 440.

    Let’s discover it with an example using famous Paris monuments!

    Simple Record Pattern Example

    Imagine we define a record Monument:

    record Monument(String name, int yearBuilt) {}

    Now, we want to print a message if the object is a Monument. Using record patterns, we can extract the name and year directly:

    static void printMonumentInfo(Object obj) {
        if (obj instanceof Monument(String name, int year)) {
            System.out.println(name + " was built in " + year);
        }
    }

    If you pass a Monument like the Eiffel Tower, it will print:

    Eiffel Tower was built in 1889

    Notice that null will never match a record pattern — so no worries about null pointer exceptions here.

    Using a Type Pattern Instead

    You could also do it in a slightly different way by first capturing the Monument, then calling its methods:

    static void printMonumentInfoTypePattern(Object obj) {
        if (obj instanceof Monument m) {
            System.out.println(m.name() + " was built in " + m.yearBuilt());
        }
    }

    Both approaches work! The record pattern version is just more compact when you need to immediately extract fields.

    Working with Generic Records

    Suppose you have a generic record like a box containing a monument:

    record Box<T>(T content) {}

    You can pattern match a specific type inside the box:

    static void printBoxedMonument(Box<String> box) {
        if (box instanceof Box<String>(String monumentName)) {
            System.out.println("Box contains: " + monumentName);
        }
    }

    ⚠️ Important:
    You must avoid unsafe casts. If you try to pattern match on a Box without a guaranteed type, it won’t compile.

    Example of wrong code:

    static void wrongBoxMatch(Box box) {
        // ERROR: Box cannot be safely cast to Box<String>
        if (box instanceof Box<String>(var name)) {
            System.out.println(name);
        }
    }

    Type Inference with var

    You don't always need to repeat the types. Java can infer them for you with var:

    static void printMonumentInfoVar(Object obj) {
        if (obj instanceof Monument(var name, var year)) {
            System.out.println(name + " was built in " + year);
        }
    }

    Shorter and cleaner!

    Nested Record Patterns: Paris in Layers

    You can even nest record patterns when working with more complex structures!

    Imagine:

    enum Style { MODERN, HISTORIC }
    record Location(double latitude, double longitude) {}
    record StyledMonument(Location location, Style style) {}
    record Area(StyledMonument north, StyledMonument south) {}

    Now, let's print the latitude of the northern monument:

    static void printNorthLatitude(Area area) {
        if (area instanceof Area(
                StyledMonument(Location(var lat, var lon), var style),
                var southMonument)) {
            System.out.println("Latitude of northern monument: " + lat);
        }
    }

    Example:

    If north represents the Arc de Triomphe and south the Louvre Museum, the program will print the Arc’s latitude!

    Nested Generic Example

    You can nest patterns with generic types too. Example:

    static void nestedBoxExample(Box<Box<String>> box) {
        if (box instanceof Box(Box(var monumentName))) {
            System.out.println("Inner box contains: " + monumentName);
        }
    }

    Here, even though you have a box inside a box, Java infers everything!

    Summary

    ✨ With record patterns and type inference, Java makes it easier to work with structured data — whether you're describing points on a map or historic Paris monuments.

    You can:

    🟣 Check and extract values in one line

    🟣 Avoid verbose code

    🟣 Safely navigate nested structures