Records and Sealed Types
miniJUGВ Java появятся записи и запечатанные типы
В багтрекере OpenJDK появился новый черновик JEP, в котором специфицируются новые языковые конструкции Java: записи и запечатанные типы. Идея их введения была предложена полтора года назад и была описана в исследовательском документе. Наконец, после долгих дискуссий и экспериментов она достигла достаточного уровня зрелости для того, чтобы с большой уверенностью сказать, что она будет реализована в одной из будущих версий Java.
Записи (records) позволят очень компактно объявлять классы, которые являются простыми носителями данных:
record Point(int x, int y) { }
Сейчас такой класс Point реализуется чрезвычайно многословно, поскольку автору кода необходимо самому написать конструктор, методы доступа к полям, equals, hashCode и toString. Это может раздражать и читателя, ведь эти члены не содержат в себе никакой особо полезной смысловой нагрузки. В записях же все эти члены генерируются компилятором автоматически и поэтому экономят время и строки кода.
Записи имеют следующие особенности:
• Они иммутабельны (все поля становятся final).
• От них нельзя отнаследоваться (они являются final).
• Они сами не могут отнаследоваться от классов.
• Если записи являются вложенными, то они являются static.
• Они не могут содержать дополнительных полей.
• Они могут содержать явный конструктор по умолчанию (в котором можно, например, сделать валидацию полей).
В остальном записи ничем не отличаются от обычных классов: они могут наследоваться от интерфейсов, содержать методы, конструкторы, статические инициализаторы, вложенные типы, иметь аннотации и т.д.
Вторая конструкция, тесно связанная с записями – это запечатанные типы (sealed types). Такие типы накладывают ограничение на типы, которые могут от них наследоваться. Делается это одним из двух способов. Первый способ – с помощью ключевого слова permits:
sealed interface Node permits A, B, C { ... }
В этом случае от интерфейса Node не могут быть отнаследованы никакие другие типы кроме A, B и C.
Второй способ – без использования ключевого слова permits. Тогда список наследников будет ограничен только теми типами, которые находятся в той же единице компиляции.
Запечатанные типы имеют следующие особенности:
• От них не могут быть отнаследованы анонимые классы и лямбды.
• Их абстрактные подтипы неявно являются запечатанными (но можно переопределить с помощью ключевого слова non-sealed).
• Их конкретные подтипы неявно являются final.
Записи и запечатанные типы вместе являются реализацией концепции алгебраических типов данных в Java. Поскольку для комфортной работы с алгебраическими типами данных также нужен паттерн-матчинг, то в будущем записи предлагается снабдить деконструирующими паттернами, а для запечатанных типов разработать механизм проверки exhaustiveness в switch-выражениях.
