Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
# Pattern Matching в Java
Pattern Matching — это мощный механизм, добавленный в Java 16 (preview) и 17 (вторая preview) для упрощения работы с условным логикой и деструктуризацией данных. Это замена традиционным instanceof проверкам и switch выражениям.
1. Проблема, которую решает Pattern Matching
Старый способ (до Java 16)
public void processPay(Object obj) {
// Массивно кода для простой проверки типа
if (obj instanceof String) {
String str = (String) obj; // Явное приведение типа
System.out.println("String length: " + str.length());
} else if (obj instanceof Integer) {
Integer num = (Integer) obj; // Явное приведение типа
System.out.println("Integer value: " + num);
} else if (obj instanceof Double) {
Double d = (Double) obj; // Явное приведение типа
System.out.println("Double value: " + d);
}
}
Новый способ (Java 16+)
public void processPay(Object obj) {
if (obj instanceof String str) {
System.out.println("String length: " + str.length()); // Переменная уже создана
} else if (obj instanceof Integer num) {
System.out.println("Integer value: " + num);
} else if (obj instanceof Double d) {
System.out.println("Double value: " + d);
}
}
Преимущества:
- Нет явного приведения типов
- Переменная создаётся автоматически
- Меньше кода, больше читаемости
2. Type Pattern (Паттерн типа)
instanceof pattern (Java 16+)
public String describeObject(Object obj) {
if (obj instanceof String str) {
return "String: " + str;
} else if (obj instanceof Integer num) {
return "Integer: " + num;
} else if (obj instanceof Double d) {
return "Double: " + d;
} else if (obj instanceof Boolean b) {
return "Boolean: " + b;
} else {
return "Unknown type";
}
}
// Использование
String result = describeObject("Hello"); // String: Hello
result = describeObject(42); // Integer: 42
result = describeObject(3.14); // Double: 3.14
Scope переменной
public void checkType(Object obj) {
if (obj instanceof String str) {
System.out.println(str); // str доступна
}
// System.out.println(str); // ОШИБКА: str недоступна вне блока if
}
// С логическим AND
if (obj instanceof String str && str.length() > 5) {
System.out.println("Long string: " + str); // str доступна
}
3. Switch Expression Pattern (Java 21+)
Классический switch (раньше)
public String describeShape(Shape shape) {
switch (shape.getType()) {
case CIRCLE:
Circle circle = (Circle) shape;
return "Circle with radius: " + circle.getRadius();
case RECTANGLE:
Rectangle rect = (Rectangle) shape;
return "Rectangle: " + rect.getWidth() + "x" + rect.getHeight();
case TRIANGLE:
Triangle tri = (Triangle) shape;
return "Triangle with sides: " + tri.getSides();
default:
return "Unknown shape";
}
}
Switch с Pattern Matching (Java 21+)
public String describeShape(Shape shape) {
return switch (shape) {
case Circle circle -> "Circle with radius: " + circle.getRadius();
case Rectangle rect -> "Rectangle: " + rect.getWidth() + "x" + rect.getHeight();
case Triangle tri -> "Triangle with sides: " + tri.getSides();
default -> "Unknown shape";
};
}
Паттерны в switch
record Point(int x, int y) {}
public String describePoint(Point p) {
return switch (p) {
case Point(int x, int y) when x == 0 && y == 0 -> "Origin";
case Point(int x, 0) -> "Point on X axis: " + x;
case Point(0, int y) -> "Point on Y axis: " + y;
case Point(int x, int y) -> "Point: (" + x + ", " + y + ")";
};
}
// Использование
String desc = describePoint(new Point(0, 0)); // Origin
desc = describePoint(new Point(5, 0)); // Point on X axis: 5
desc = describePoint(new Point(3, 4)); // Point: (3, 4)
4. Record Pattern (Java 21+)
Record (неизменяемый класс)
public record User(String name, String email, int age) {}
public void processUser(User user) {
// Pattern matching на fields record'а
if (user instanceof User(var name, var email, var age)) {
System.out.println("Name: " + name);
System.out.println("Email: " + email);
System.out.println("Age: " + age);
}
}
// Вложенные record'ы
public record Address(String street, String city) {}
public record Person(String name, Address address) {}
public String describeAddress(Person person) {
return switch (person) {
case Person(var name, Address(var street, var city)) ->
name + " lives at " + street + ", " + city;
default -> "Unknown";
};
}
5. Guard Conditions (Java 17+)
when с instanceof
public String validateValue(Object obj) {
if (obj instanceof String str && str.length() > 0) {
return "Non-empty string: " + str;
} else if (obj instanceof Integer num && num > 0) {
return "Positive integer: " + num;
} else if (obj instanceof Integer num && num < 0) {
return "Negative integer: " + num;
} else {
return "Invalid";
}
}
when в switch (Java 21+)
public String categorize(Object obj) {
return switch (obj) {
case String s when s.length() > 10 -> "Long string";
case String s when s.length() > 0 -> "Short string";
case Integer i when i > 0 -> "Positive number";
case Integer i when i < 0 -> "Negative number";
case Integer i -> "Zero";
default -> "Unknown";
};
}
6. Практические примеры
API Response обработка
public sealed interface ApiResponse {}
public record SuccessResponse(String data) implements ApiResponse {}
public record ErrorResponse(int code, String message) implements ApiResponse {}
public record EmptyResponse() implements ApiResponse {}
public void handleApiResponse(ApiResponse response) {
switch (response) {
case SuccessResponse(var data) ->
System.out.println("Success: " + data);
case ErrorResponse(var code, var message) ->
System.out.println("Error [" + code + "]: " + message);
case EmptyResponse() ->
System.out.println("Empty response");
};
}
JSON обработка
public Number processNumber(Object obj) {
return switch (obj) {
case Integer i when i > 0 -> i * 2;
case Integer i -> -i;
case Double d when d > 0 -> d * 2;
case Double d -> -d;
case String s -> {
try {
yield Double.parseDouble(s);
} catch (NumberFormatException e) {
yield 0.0;
}
}
default -> throw new IllegalArgumentException("Unsupported type");
};
}
Validation chain
public class Validator {
public boolean validate(Object obj) {
return obj instanceof String str && isValidEmail(str) ||
obj instanceof Integer num && isValidAge(num) ||
obj instanceof Boolean b && b;
}
private boolean isValidEmail(String email) {
return email.contains("@");
}
private boolean isValidAge(Integer age) {
return age >= 18 && age <= 120;
}
}
7. История и версии
| Версия | Что добавилось |
|---|---|
| Java 16 | instanceof with pattern (preview) |
| Java 17 | instanceof pattern (finalized) |
| Java 18 | switch patterns (preview) |
| Java 19 | record patterns (preview), switch patterns (preview) |
| Java 20 | record patterns (second preview), switch patterns (second preview) |
| Java 21 | switch patterns (finalized), record patterns (preview) |
8. Когда использовать
Используйте Pattern Matching для:
- Проверки типов объектов
- Деструктуризации данных (особенно record'ов)
- Условной логики на основе типов
- Замены множества instanceof и cast
Не используйте для:
- Простых boolean проверок
- Логики, которая должна быть в отдельных методах
9. Альтернативы и сравнение
// Способ 1: Старый instanceof с cast
if (obj instanceof String) {
String str = (String) obj;
process(str);
}
// Способ 2: Pattern Matching (Java 16+)
if (obj instanceof String str) {
process(str);
}
// Способ 3: Strategy Pattern (если много логики)
strategy.process(obj);
// Способ 4: Visitor Pattern (для сложных иерархий)
obj.accept(visitor);
Заключение
Pattern Matching — это революционная возможность в Java для упрощения кода и повышения его читаемости. Особенно мощна в комбинации с records и switch expression'ами. В Java 21+ это уже finalized feature и рекомендуется использовать в новых проектах.