Record: неизменяемые данные в одну строку
Record (Java 16+) сам создаёт конструктор, аксессоры, equals, hashCode и toString. Но неизменяемость поверхностная: список внутри record по-прежнему можно изменить снаружи.
Подробно
Запись record Point(int x, int y) {} компилятор разворачивает в финальный класс: приватные final-поля, канонический конструктор, методы доступа x() и y() (без префикса get), а также equals, hashCode и toString по всем компонентам.
Record нельзя наследовать от другого класса, он неявно final, а поля нельзя переприсвоить. Для проверок используют компактный конструктор: он пишется без списка параметров и выполняется до присваивания полей.
Главная ловушка: неизменяемость поверхностная. Если компонент record - это List или массив, то содержимое можно менять через ссылку. Поэтому в компактном конструкторе копируют коллекцию.
- Подходит: DTO, ключи Map, результаты запросов, значения.
- Не подходит: JPA-сущности (нужен конструктор без аргументов и изменяемость).
Пример из практики
record Order(long id, List<String> items) {
Order {
if (items == null) throw new IllegalArgumentException();
items = List.copyOf(items);
}
}
Теперь order.items().add("x") бросит UnsupportedOperationException, и исходный список снаружи на record не влияет.
Проверьте себя
Как называется метод доступа к компоненту name у record Person(String name)?
Показать ответ
name() - без префикса get. Это метод, который компилятор генерирует автоматически.
У record аксессор называется так же, как компонент: person.name(). Привычный getName() появится только если вы напишете его вручную.
Источник: Java SE 21 API: java.lang.Record