Що таке Record і як він допомагає створювати незмінні класи?
Один рядок замість 20+. Автоматично:
Junior Level
Record — це спеціальний тип класу в Java (з’явився в Java 14, стабільний з Java 16), який автоматично створює незмінний клас для зберігання даних.
До Record
public final class Point {
private final int x;
private final int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() { return x; }
public int getY() { return y; }
@Override public boolean equals(Object o) { ... }
@Override public int hashCode() { ... }
@Override public String toString() { ... }
}
З Record
public record Point(int x, int y) {}
Один рядок замість 20+. Автоматично:
- Клас
final - Поля
private final - Конструктор
- Гетери (
x(),y()— неgetX()) equals(),hashCode(),toString()
Middle Level
Що робить компілятор за вас
public record User(String name, int age) {}
Генерується:
public final class User extends java.lang.Record {
private final String name;
private final int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
public String name() { return name; }
public int age() { return age; }
// equals, hashCode, toString — по всіх полях
}
Поверхнева незмінність
record гарантує, що посилання не зміняться. Але якщо поле — мутабельна колекція, її вміст можна змінити:
public record Order(Long id, List<String> items) {}
Order order = new Order(1L, new ArrayList<>(List.of("A")));
order.items().add("B"); // МОЖНА! items — той самий список
Рішення — компактний конструктор
public record Order(Long id, List<String> items) {
public Order {
items = List.copyOf(items); // захисна копія
}
}
Коли використовувати
- DTO — передача даних між шарами
- Ключі в Map — стабільний
hashCode - Локальні структури — тимчасове зберігання кортежів
Senior Level
Обмеження
- Не може наслідуватися від інших класів (вже наслідує
java.lang.Record) - Не може бути базовим класом (завжди
final) - Не може мати
instanceполя крім оголошених у заголовку - Не може бути
abstract
Record vs Lombok @Value vs звичайний final class
| Record | Lombok @Value | Final class | |
|---|---|---|---|
| Boilerplate | Мінімум | Мінімум | Вручну |
| Наслідування | ❌ | Можна | Можна |
| Extra-поля | ❌ | Можна | Можна |
| Залежності | JDK | Lombok | Немає |
Компактний конструктор і валідація
public record User(String email, int age) {
public User {
Objects.requireNonNull(email, "Email required");
if (age < 0) throw new IllegalArgumentException("Age must be positive");
}
}
Кастомні методи
public record Rectangle(int width, int height) {
public int area() {
return width * height;
}
}
Резюме для Senior
record— спеціальна мовна конструкція для незмінних класів-значень. Це не просто sugar — record має власні обмеження (не можна наслідувати, не можна мати instance-поля крім declared).- Радикально знижує обсяг коду та ймовірність помилки в
equals/hashCode - Ручне копіювання колекцій все ще необхідне
- Використовуйте для DTO, ключів Map, тимчасових структур
- Не може брати участь в ієрархії наслідування
Шпаргалка для інтерв’ю
Обов’язково знати:
- Record (Java 14+, стабільний Java 16) — спеціальна мовна конструкція для незмінних класів-значень
- Автоматично:
finalклас,private finalполя, конструктор, гетери (name()неgetName()), equals/hashCode/toString - Поверхнева незмінність: посилання незмінні, але мутабельні колекції можна змінювати
- Компактний конструктор:
public Order { items = List.copyOf(items); }— для захисного копіювання - Обмеження: немає наслідування, немає extra instance-полів, немає
abstract - Record vs Lombok @Value: Record — JDK, без залежностей; Lombok — більше гнучкості
Часті уточнювальні запитання:
- Record робить deep copy колекцій? — Ні, тільки shallow; потрібно вручну в компактному конструкторі
- Чи можна додати поле в Record? — Ні, тільки оголошені в заголовку
- Record можна наслідувати? — Ні, завжди
final; не може бути базовим класом - Гетери в Record — getX()? — Ні, просто
x()— без префікса get
Червоні прапорці (НЕ говорити):
- «Record повністю незмінний» — колекції потрібно копіювати вручну
- «Record можна розширити» — завжди final, немає наслідування
- «Record замінює Lombok» — Lombok @Builder, @Singular дають більше функціональності
- «Record — це просто sugar» — record має власні обмеження та семантику
Пов’язані теми:
- [[1. Що таке незмінний (immutability) об’єкт]]
- [[3. Як створити незмінний клас в Java]]
- [[26. Як реалізувати Builder pattern для незмінного класу]]
- [[27. Чи можна використовувати незмінні об’єкти як ключі в HashMap]]
- [[29. Як правильно працювати з колекціями в незмінних класах]]