• Вышло несколько новых черновиков JEP. Рассмотрим каждый из них.
Unnamed local variables and patterns. В этом JEP предлагается добавить в язык безымянные переменные и паттерны, которые будут обозначаться символом _
(подчёркивание).
Это очень полезное улучшение: оно позволит не давать имя переменной, которая в дальнейшем не будет использоваться. Такая ситуация возникает довольно часто, например, в блоке try-catch
, когда важен только тип исключения:
try { int i = Integer.parseInt(s); ... } catch (NumberFormatException _) { System.out.println("Bad number: " + s); }
Другой частый случай – лямбда-выражения:
map.computeIfAbsent(k, _ -> new ArrayList<>());
Ещё один пример – паттерн-матчинг:
void pingDevice(Device d) { String ip = switch (d) { case Printer(_, _, _, String ipp) -> ipp; case Server(_, String ips) -> ips; }; ping(ip); }
Полный список случаев, когда можно будет использовать подчёркивание:
- Объявление локальной переменной в блоке.
- Спецификация ресурса в
try-with-resources
. - Объявление базового цикла
for
или улучшенного циклаfor
. - Переменная паттерна.
- Параметр
catch
. - Параметр лямбда-выражения.
Заметим, что в данный список не входят параметры методов классов и интерфейсов. В них по прежнему придётся давать имена всем параметрам. Почему такое решение было принято, можно почитать в этой ветке рассылки проекта Amber.
Record Patterns (Second Preview). Это второе preview паттернов записей (первое попало в Java 19).
В этой итерации три главных изменения.
Во-первых, добавляется поддержка вывода типов в записях-дженериках:
record Box<T>(T t) {} static void test(Box<String> box) { if (box instanceof Box(var s)) { // Выводится Box<String>(var s) System.out.println("String " + s); } }
Во-вторых, паттерны записей смогут присутствовать в объявлениях улучшенного цикла for
:
record Pair<T, U>(T first, U second) {} static void loop(List<Pair<String, Integer>> pairs) { for (Pair(var first, var second) : pairs) { System.out.println(first + ", " + second); } }
В-третьих, исчезает поддержка именованных паттернов записей. Это значит, что такой код уже не будет компилироваться:
if (obj instanceof Point(var x, var y) p) { ... }
Однако по этому пункту возникла дискуссия в рассылке, и пока непонятно, действительно ли примут решение убрать такую полезную возможность языка. Брайн Гетц считает, что с введением такой возможности поспешили и что если её откатить, то это позволит более тщательно её продумать и вернуть обратно в будущем в этой или иной форме.
Pattern Matching for switch
(Fourth Preview). Это уже четвёртая итерация паттерн-матчинга (предыдущие три попали в Java 17, 18 и 19). В новой версии два главных изменения: упрощённая грамматика switch labels и поддержка вывода типов для паттернов дженериков.
Упрощённая грамматика большее значение представляет для разработчиков компиляторов и IDE. А вывод типов в switch
выглядит следующим образом:
Collection<String> collection = ...; switch (collection) { case List<> l -> ... // Выводится List<String> case Set<> s -> ... // Выводится Set<String> case Queue q -> ... // Ничего не выводится, сырой тип Queue ... }
Однако для записей diamond-оператор необязателен:
record Pair<T, U>(T first, U second) {} static void test(Pair<String, Integer> pair) { switch (pair) { case Pair(var fst, var snd) -> ... // Выводится Pair<String, Integer> ... } }
То же самое касается и паттерн-матчинга через instanceof
, пример которого уже был приведён выше (см. пример с Box<T>
).
64 bit object headers. Цель этого JEP – уменьшение размера заголовков с 96/128 до 64 бит. Это позволит уменьшить потребление памяти кучей приблизительно на 6-12%, что, в свою очередь, уменьшит нагрузку на GC и CPU.
Работа по сжатию заголовков ведётся в проекте Lilliput, который был предложен в марте 2021 года Романом Кеннке, впоследствии и ставшим лидером проекта. Ранее Роман сообщил, что в проекте удалось добиться значительных успехов и что уже ведётся работа над следующим этапом: сжатием заголовка до 32 бит.
• Брайан Гетц предложил внести изменения в Java, облегчающие вхождение новичков в язык. Он выложил документ с заголовком "Paving the on-ramp" ("прокладывая заезд на автостраду"), где изложил свои мысли относительно возможных упрощений, которые сделают кривую изучения языка более пологой.
Когда новичок впервые изучает Java, он сразу же сталкивается с большим числом незнакомых концепций, которых нельзя избежать при написании даже самой простой программы:
public class HelloWorld { public static void main(String[] args) { System.out.println("Hello World"); } }
Для полного понимания этого кода придётся разобраться чуть ли не со всеми основными аспектами языка:
- Уровни видимости (
public
). - Классы.
- Методы.
static
.main
.- Строки.
- Массивы (
String[]
). - Поля (
out
). - Константы (
out
).
Брайан Гетц предлагает три упрощения, которые помогут изучающим язык начать с минимально короткой программы и постепенно переходить к более сложным концепциям.
Во-первых, можно сделать public
, static
и параметр args
опциональными. Тогда код упростится до следующего:
class HelloWorld { void main() { System.out.println("Hello World"); } }
Во-вторых, можно ввести концепцию безымянных классов, что позволит объявлять поля и методы без объявления класса. Это позволит упростить код ещё сильнее:
void main() { System.out.println("Hello World"); }
Наконец, можно сделать некоторые наиболее часто используемые методы статическими (println
, readln
) и импортировать их автоматически (как автоматически импортируются все классы в java.lang
). В итоге код сократится до самого минимума:
void main() { println("Hello World"); }
Сейчас всё это существует исключительно на уровне концепции, которая активно обсуждается в рассылке, но возможно что-то из предложенных идей будет в будущем реализовано в языке.
• Вышел Java Annotated Monthly от JetBrains за октябрь.