🎯 Record Patterns в Java 21: как компилятор превращает деструктуризацию в bytecode
После двух preview (Java 19-20), Record Patterns стали финальной фичей в Java 21. Разберем механику работы под капотом.
🔹 Что такое Record Patterns
Это расширение pattern matching для деструктуризации record классов:
🔹 Nested patterns — вложенная деструктуризация
Мощь раскрывается с вложенными record'ами:
Компилятор генерирует код примерно так:
Для вложенных patterns компилятор создает каскад instanceof проверок и вызовов accessor методов.
🔹 Pattern Matching для switch
Record patterns работают в switch (JEP 441 - тоже финализирован в Java 21):
🔹 Guarded patterns
Можно добавлять условия:
🔹 Важное изменение с preview
В финальной версии убрали поддержку record patterns в enhanced for:
Причина: семантическая неоднозначность и возможные проблемы с нулевыми элементами.
📌 Record Patterns + Pattern Matching for switch — это огромный шаг к функциональному стилю в Java. Код становится декларативным, компактным и безопасным.
🐸 Библиотека джависта
#CoreJava
После двух preview (Java 19-20), Record Patterns стали финальной фичей в Java 21. Разберем механику работы под капотом.
🔹 Что такое Record Patterns
Это расширение pattern matching для деструктуризации record классов:
record Point(int x, int y) {}
// До Java 21
if (obj instanceof Point point) {
int x = point.x();
int y = point.y();
// use x, y
}
// Java 21
if (obj instanceof Point(int x, int y)) {
// x и y автоматически в scope
System.out.println(x + y);
}
🔹 Nested patterns — вложенная деструктуризация
Мощь раскрывается с вложенными record'ами:
record Point(int x, int y) {}
record Rectangle(Point upperLeft, Point lowerRight) {}
// Одна строка вместо цепочки вызовов
if (shape instanceof Rectangle(Point(int x1, int y1),
Point(int x2, int y2))) {
int area = Math.abs((x2-x1) * (y2-y1));
}
Компилятор генерирует код примерно так:
// Исходный код
if (obj instanceof Point(int x, int y)) {
process(x, y);
}
// Что генерирует компилятор (упрощенно)
if (obj instanceof Point __temp) {
int x = __temp.x();
int y = __temp.y();
process(x, y);
}
Для вложенных patterns компилятор создает каскад instanceof проверок и вызовов accessor методов.
🔹 Pattern Matching для switch
Record patterns работают в switch (JEP 441 - тоже финализирован в Java 21):
sealed interface Shape permits Circle, Rectangle, Triangle {}
record Circle(double radius) implements Shape {}
record Rectangle(double width, double height) implements Shape {}
record Triangle(double a, double b, double c) implements Shape {}
double area(Shape shape) {
return switch(shape) {
case Circle(double r) -> Math.PI * r * r;
case Rectangle(double w, double h) -> w * h;
case Triangle(double a, double b, double c) -> {
double s = (a + b + c) / 2;
yield Math.sqrt(s * (s-a) * (s-b) * (s-c));
}
};
}
🔹 Guarded patterns
Можно добавлять условия:
String classify(Object obj) {
return switch(obj) {
case Point(int x, int y) when x == y -> "diagonal";
case Point(int x, int y) when x > y -> "above diagonal";
case Point(int x, int y) -> "below diagonal";
default -> "not a point";
};
}
🔹 Важное изменение с preview
В финальной версии убрали поддержку record patterns в enhanced for:
// Работало в preview
for (Point(int x, int y) : points) { }
// Больше не работает в Java 21 final
Причина: семантическая неоднозначность и возможные проблемы с нулевыми элементами.
#CoreJava
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥5❤2👍2👏2