Что такое pattern matching в Java и как он используется?

«Что такое pattern matching в Java и как он используется?» — вопрос из категории Java Core, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Pattern matching — это механизм, позволяющий проверять структуру объекта и извлекать из него значения в одном выражении. В Java он постепенно внедряется через несколько версий.

Основные формы pattern matching в Java:

1. Pattern matching для instanceof (Java 16+)

// Старый подход (до Java 16)
if (obj instanceof String) {
    String s = (String) obj;
    System.out.println(s.length());
}

// Новый подход с pattern matching
if (obj instanceof String s) {
    // Переменная 's' автоматически приводится к String
    System.out.println(s.length());
}

// Можно использовать в условиях
if (obj instanceof String s && s.length() > 5) {
    System.out.println("Длинная строка: " + s);
}

2. Pattern matching в switch (Java 21+, preview в Java 17-20)

// Типизированный pattern matching в switch
String format(Object obj) {
    return switch (obj) {
        case Integer i -> String.format("int: %d", i);
        case Long l    -> String.format("long: %d", l);
        case Double d  -> String.format("double: %f", d);
        case String s  -> String.format("String: %s", s);
        case null      -> "null";
        default        -> obj.toString();
    };
}

// С guard-условиями (when)
String checkNumber(Number n) {
    return switch (n) {
        case Integer i when i > 0 -> "Положительное целое";
        case Integer i when i == 0 -> "Ноль";
        case Integer i -> "Отрицательное целое";
        case Double d when d > 0 -> "Положительное дробное";
        default -> "Другое число";
    };
}

3. Record patterns (Java 21+, preview)

record Point(int x, int y) {}

// Деструктуризация record в pattern matching
void printPoint(Object obj) {
    if (obj instanceof Point(int x, int y)) {
        System.out.printf("Точка: x=%d, y=%d%n", x, y);
    }
}

// Вложенные record patterns
record Rectangle(Point topLeft, Point bottomRight) {}

double area(Object obj) {
    return switch (obj) {
        case Rectangle(Point(var x1, var y1), Point(var x2, var y2)) -> 
            Math.abs((x2 - x1) * (y2 - y1));
        default -> 0.0;
    };
}

Преимущества pattern matching:

  1. Упрощение кода — меньше boilerplate-кода для проверок и приведений типов
  2. Безопасность — исключаются ошибки приведения типов
  3. Выразительность — код лучше отражает намерения разработчика
  4. Поддержка null — явная обработка null в switch

Ограничения и особенности:

  • Pattern matching для instanceof доступен с Java 16 (final)
  • Pattern matching в switch — с Java 21 (final), был в preview с Java 17
  • Record patterns — с Java 21 (preview)
  • Переменные в pattern matching имеют ограниченную область видимости (scope)

Практическое применение:

  • Обработка разнотипных данных (парсинг, сериализация)
  • Реализация посетителей (visitor pattern) без наследования
  • Обработка AST (abstract syntax trees) в компиляторах и анализаторах