Java Pattern Matching

Simplify instanceof checks and switch statements with pattern matching (Java 16+)

java (16+) 2025-11-03 pattern-matching switch instanceof java16

Description

Pattern matching simplifies common coding patterns by combining type checking and casting into a single operation. It reduces boilerplate code and makes programs more readable and less error-prone.

Key Features

  • Pattern matching for instanceof: Automatically casts after type check
  • Pattern matching for switch: Use patterns in switch expressions
  • Type patterns: Match against types and bind variables
  • Guarded patterns: Add conditions to pattern matches

Benefits

  • Less boilerplate: No explicit casting needed
  • Safer code: Compiler ensures type safety
  • More readable: Clear intent in code
  • Exhaustiveness checking: Compiler can verify all cases handled

Evolution

  • Java 14: Pattern matching for instanceof (preview)
  • Java 16: Pattern matching for instanceof (standard)
  • Java 17: Pattern matching for switch (preview)
  • Java 19: Pattern matching for switch (standard)
  • Java 21: Record patterns, pattern matching improvements

Code

RAW
public class PatternMatchingUtils {        // Pattern matching with instanceof (Java 16+)    public static String process(Object obj) {        if (obj instanceof String str) {            return "String: " + str.toUpperCase();        } else if (obj instanceof Integer num) {            return "Integer: " + (num * 2);        } else if (obj instanceof Number num) {            return "Number: " + num.doubleValue();        }        return "Unknown type";    }        // Pattern matching with guarded patterns    public static String processWithGuard(Object obj) {        if (obj instanceof String str && str.length() > 5) {            return "Long string: " + str;        } else if (obj instanceof String str) {            return "Short string: " + str;        }        return "Not a string";    }        // Pattern matching in switch (Java 17+)    public static String processWithSwitch(Object obj) {        return switch (obj) {            case String str -> "String: " + str;            case Integer i -> "Integer: " + i;            case Double d -> "Double: " + d;            case null -> "Null value";            default -> "Unknown: " + obj.getClass().getSimpleName();        };    }        // Pattern matching with sealed classes    public static double calculateArea(Shape shape) {        return switch (shape) {            case Circle c -> Math.PI * c.radius() * c.radius();            case Rectangle r -> r.width() * r.height();            case Triangle t -> 0.5 * t.base() * t.height();        };    }        // Pattern matching with records    public static String describe(Person person) {        return switch (person) {            case Person(String name, int age) when age < 18 -> name + " is a minor";            case Person(String name, int age) when age >= 65 -> name + " is a senior";            case Person(String name, int age) -> name + " is an adult";        };    }}
RAW
// Old way (before pattern matching)Object obj = "Hello";if (obj instanceof String) {    String str = (String) obj; // Explicit cast    System.out.println(str.length());}// New way with pattern matching (Java 16+)Object obj2 = "Hello";if (obj2 instanceof String str) {    // str is automatically cast and available    System.out.println(str.length());}// Pattern matching with conditionsObject obj3 = "Hello World";if (obj3 instanceof String s && s.length() > 5) {    System.out.println("Long string: " + s);}// Pattern matching in switch (Java 17+)Object value = 42;String result = switch (value) {    case String s -> "String: " + s;    case Integer i -> "Integer: " + i;    case Double d -> "Double: " + d;    case null -> "Null";    default -> "Unknown";};// Pattern matching with sealed classesShape shape = new Circle(5.0);double area = switch (shape) {    case Circle c -> Math.PI * c.radius() * c.radius();    case Rectangle r -> r.width() * r.height();    case Triangle t -> 0.5 * t.base() * t.height();};// Pattern matching with recordsrecord Person(String name, int age) {}Person person = new Person("Alice", 25);String description = switch (person) {    case Person(String name, int age) when age < 18 -> name + " is a minor";    case Person(String name, int age) -> name + " is " + age + " years old";};// Nested pattern matchingrecord Point(int x, int y) {}record Line(Point start, Point end) {}Line line = new Line(new Point(0, 0), new Point(10, 10));String lineInfo = switch (line) {    case Line(Point(int x1, int y1), Point(int x2, int y2)) ->        "Line from (" + x1 + "," + y1 + ") to (" + x2 + "," + y2 + ")";};

Comments

No comments yet. Be the first to comment!