Новости Java #46

• Вышло несколько новых черновиков 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");
    }
}

Для полного понимания этого кода придётся разобраться чуть ли не со всеми основными аспектами языка:

  1. Уровни видимости (public).
  2. Классы.
  3. Методы.
  4. static.
  5. main.
  6. Строки.
  7. Массивы (String[]).
  8. Поля (out).
  9. Константы (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 за октябрь.

Подписывайтесь на канал в Telegram, чтобы не пропускать новости.

Все материалы на этом сайте выложены под лицензией CC BY-SA 4.0
© Евгений Козлов, 2017-2022
Feed