Что такое record
record (Java 16) — компактная форма неизменяемого носителя данных. Из объявления record Point(int x, int y) компилятор генерирует: private final поля-компоненты, канонический конструктор, аксессоры (x(), y() — без префикса get), а также equals/hashCode/toString строго по компонентам.
Это убирает горы шаблонного кода у DTO/value-объектов и делает их корректными по умолчанию (правильные equals/hashCode из коробки).
record Point(int x, int y) {}
// сгенерировано: поля, конструктор, x()/y(), equals/hashCode/toString
Канонический и компактный конструкторы
Канонический конструктор принимает все компоненты. Для валидации/нормализации удобен компактный конструктор — без списка параметров: в нём проверяют аргументы и при необходимости нормализуют их перед неявным присваиванием полей.
Можно добавлять и дополнительные конструкторы (они обязаны делегировать в канонический), статические фабрики и методы. Важная связка с неизменяемостью: record не делает защитных копий за вас — если компонент изменяемый (List, массив), его нужно скопировать в компактном конструкторе и при выдаче, иначе «неизменяемая» запись протекает.
record Period(LocalDate from, List<Event> events) {
Period { // компактный конструктор
if (from == null) throw new IllegalArgumentException("from");
events = List.copyOf(events); // защитная копия изменяемого компонента
}
}
Ограничения
record неявно final и не может наследовать класс (extends запрещён), но может реализовывать интерфейсы. Всё состояние задаётся компонентами — нельзя добавить произвольное instance-поле (только static).
Эти ограничения — следствие сути: record моделирует «прозрачный» агрегат данных, у которого идентичность определяется значениями компонентов, а не ссылкой.
Когда применять
Records идеальны для DTO, value-объектов, составных ключей Map, возврата нескольких значений из метода и как варианты в sealed-иерархиях для pattern matching.
Не подходят там, где нужна изменяемость или identity-семантика (JPA-сущности с жизненным циклом, объекты с поведением и инкапсулированным изменяемым состоянием) — для них обычный класс.
Как отвечать на собеседовании
Перечислите, что генерирует record (final-поля, конструктор, аксессоры без get, equals/hashCode/toString по компонентам), покажите компактный конструктор для валидации и обязательно — что record НЕ делает защитных копий (изменяемый компонент надо копировать сам). Назовите ограничения (final, нет extends, состояние только из компонентов) и уместные сценарии (DTO/value/ключи/варианты sealed).