JavaRush /Курсы /JAVA 25 SELF /Pattern Matching for instanceof

Pattern Matching for instanceof

JAVA 25 SELF
65 уровень , 1 лекция
Открыта

1. Проблема классического instanceof

Давайте начнём с небольшой ностальгии. До Java 16, когда вам нужно было проверить тип объекта и затем использовать его как этот тип, приходилось писать многословный шаблон с проверкой instanceof и явным приведением:

Object obj = ...; // какой-то объект

if (obj instanceof String) {
    String s = (String) obj;
    System.out.println("Длина строки: " + s.length());
}

Скучный, но частый шаблон

Этот паттерн встречается очень часто — обработчики событий, работа с разнородными коллекциями, бизнес-логика с наследованием и т. п.

Почему это неудобно

  • Дублирование кода — приходится дважды указывать тип: и в instanceof, и в приведении.
  • Риск ошибки — легко случайно привести к не тому типу и получить ClassCastException.
  • «Шумный» код — ухудшает читаемость, особенно при множественных проверках.

2. Pattern Matching for instanceof: Новый синтаксис

В Java 16 добавили сопоставление с образцом (pattern matching) для instanceof. Теперь проверяем тип и сразу объявляем переменную нужного типа, доступную внутри ветки if.

Новый синтаксис

if (obj instanceof String s) {
    // s — это уже строка!
    System.out.println("Длина строки: " + s.length());
}
  • После типа в instanceof пишем имя новой переменной: String s.
  • Переменная доступна только внутри блока, где условие истинно.
  • Не нужно писать приведение (String) — компилятор всё гарантирует.

В чём магия? Компилятор проверяет тип и, если он подходит, «раскрывает» переменную нужного типа. Иначе блок просто не выполняется.

Как это выглядит в реальном коде

Object obj = "Привет, Java 16+!";

if (obj instanceof String s) {
    System.out.println("Верхний регистр: " + s.toUpperCase());
} else {
    System.out.println("Это не строка!");
}

3. Безопасность и читаемость: почему это круто

Исключается ошибка ClassCastException

Object obj = 123;
// String s = (String) obj; // Бум! Исключение.

С pattern matching переменная создаётся только при успешной проверке типа — «неправильного» приведения просто нет.

Код становится короче и понятнее
Две строки превращаются в одну. Меньше «шумного» кода — проще читать и поддерживать.

Пример: обработка разных типов

public static void printInfo(Object obj) {
    if (obj instanceof String s) {
        System.out.println("Строка длиной " + s.length());
    } else if (obj instanceof Integer i) {
        System.out.println("Целое число: " + (i + 1));
    } else {
        System.out.println("Неизвестный тип: " + obj);
    }
}

4. Примеры использования и нюансы

Проверка нескольких типов

Object value = ...;

if (value instanceof String s) {
    System.out.println("Это строка: " + s);
} else if (value instanceof Number n) {
    System.out.println("Это число: " + n);
} else {
    System.out.println("Что-то ещё: " + value);
}

Использование с null
Если объект равен null, то instanceof всегда вернёт false — NPE не будет, но блок не выполнится.

Object obj = null;

if (obj instanceof String s) {
    // Этот блок НИКОГДА не выполнится, если obj == null
    System.out.println("Строка: " + s);
} else {
    System.out.println("obj — это null или не строка");
}

Pattern matching с наследованием

class Animal {}
class Dog extends Animal {
    void bark() { System.out.println("Гав!"); }
}

Animal a = new Dog();

if (a instanceof Dog d) {
    d.bark(); // Можем вызывать методы Dog без приведения!
}

Напоминаем, порядок проверок важен: идите от более конкретного к более общему, иначе «узкие» проверки могут не сработать.

Сравнение: старый и новый подход

Старый способ Новый способ (pattern matching)
if (obj instanceof Cat) {
    Cat c = (Cat) obj;
    c.meow();
}
if (obj instanceof Cat c) {
    c.meow();
}

5. Ограничения pattern matching для instanceof

  • Область видимости переменной. Переменная из образца видна только в той ветке, где проверка истинна.
if (obj instanceof String s) {
    System.out.println(s); // s доступна
}
// System.out.println(s); // Ошибка! s не видна здесь
  • Нельзя объявлять несколько переменных разных типов в одном условии.
// Ошибка компиляции:
if (obj instanceof String s || obj instanceof Integer i) {
    // ...
}
  • Требуется Java 16+. На более старых версиях JDK новый синтаксис не поддерживается.

6. Практические примеры (на базе простого приложения)

Представим простой Task Manager с разными типами задач.

Классы

class Task {
    String title;
    public Task(String title) { this.title = title; }
}

class BugTask extends Task {
    int severity;
    public BugTask(String title, int severity) {
        super(title);
        this.severity = severity;
    }
}

class FeatureTask extends Task {
    String feature;
    public FeatureTask(String title, String feature) {
        super(title);
        this.feature = feature;
    }
}

Обработка с pattern matching

public static void processTask(Task t) {
    if (t instanceof BugTask bug) {
        System.out.println("Баг: " + bug.title + ", критичность: " + bug.severity);
    } else if (t instanceof FeatureTask feature) {
        System.out.println("Фича: " + feature.title + ", модуль: " + feature.feature);
    } else if (t instanceof Task task) {
        System.out.println("Обычная задача: " + task.title);
    }
}

7. Полезные нюансы

Таблица: Pattern Matching для instanceof — плюсы и минусы

Плюсы Минусы/Ограничения
Меньше кода, выше читаемость Требует Java 16+
Нет риска ClassCastException Переменная видна только внутри if-блока
Безопасность типов на уровне компилятора Не работает для нескольких типов в одном условии
Удобно для обработки наследования В старых IDE и сборках может не поддерживаться
Подходит для любых классов

Визуальная схема: как работает pattern matching для instanceof

+---------------------------+
|      Object obj           |
+---------------------------+
            |
            v
  if (obj instanceof Type t)
            |
      Да           Нет
   (true)        (false)
    |               |
    v               v
 t доступна     t не существует
   (код)           (нет доступа)

8. Типичные ошибки при использовании pattern matching for instanceof

Ошибка №1: Попытка использовать переменную вне блока if. Объявили переменную в образце, вышли из блока — переменной больше нет. Компилятор справедливо ругается: «Кто такая s?»

Ошибка №2: Ожидание, что instanceof сработает для null. Если объект равен null, условие instanceof всегда ложно, переменная не создаётся. Обрабатывайте null отдельно при необходимости.

Ошибка №3: Использование нового синтаксиса на старой версии JDK/IDE. На Java 11 и ниже сопоставление с образцом для instanceof недоступно — получите ошибку синтаксиса. Проверьте версию JDK.

Ошибка №4: Путаница с областью видимости. Переменная из образца доступна только в той ветке, где проверка истинна. За пределами — её не существует.

Ошибка №5: Ожидание поддержки нескольких типов одновременно. Нельзя объявить сразу две переменные разных типов в одном условии: if (obj instanceof String s || obj instanceof Integer i) — так нельзя. Для каждого типа — своя проверка.

1
Задача
JAVA 25 SELF, 65 уровень, 1 лекция
Недоступна
Интеллектуальный анализатор данных 🔍
Интеллектуальный анализатор данных 🔍
1
Задача
JAVA 25 SELF, 65 уровень, 1 лекция
Недоступна
Идентификация питомцев в приюте 🐾
Идентификация питомцев в приюте 🐾
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ