Что даёт неизменяемость (immutability) объекта?
- Зачем нужны неизменяемые объекты?
- Как сделать класс неизменяемым?
- Почему String неизменяемый?
Неизменяемый объект потокобезопасен без синхронизации, безопасен как ключ Map / элемент Set и его можно свободно кэшировать и делить.
- Как сделать: final-класс, private final поля, нет сеттеров, защитные копии изменяемых полей
- record — быстрый способ, но копии вложенных коллекций всё равно на вас
А ещё Цена — новые объекты при каждом «изменении»
Подробно
У неизменяемого (immutable) объекта наблюдаемое состояние не меняется после создания. Отсюда преимущества:
- потокобезопасность — состояние нечем испортить гонкой, объект можно передавать между потоками без блокировок;
- безопасность в хеш-коллекциях — хеш не изменится после добавления в
HashMapилиHashSet, объект не «потеряется»; - кэширование и переиспользование — один экземпляр можно отдавать всем (как
Stringи пул строк); - простота рассуждений — объект нельзя изменить «снаружи» по ссылке.
Как сделать класс неизменяемым:
- запретить наследование (
finalкласс или приватный конструктор); - все поля
private final; - никаких сеттеров и методов, меняющих состояние;
- изменяемые поля (списки, даты старого API) копировать при создании и не отдавать наружу как есть — возвращать копию или неизменяемое представление.
Record даёт пункты 1–3 автоматически, но если поле — список, неизменяемость нужно обеспечить самому (List.copyOf). Цена подхода — «изменение» создаёт новый объект, поэтому для частых правок используют изменяемые билдеры (StringBuilder).
Пример
public record Order(long id, List<String> items) {
public Order {
items = List.copyOf(items); // защитная неизменяемая копия
}
}Что хотят услышать
- Три выгоды: потокобезопасность, ключи коллекций, кэширование.
- Как сделать класс неизменяемым, включая защитные копии.
- Ограничение record с изменяемыми полями — плюс.
Частые ошибки
- Связывать неизменяемость с хранением в стеке.
- Думать, что она убирает NPE.
Проверьте себя
Один верный вариант. Подумайте, потом откройте ответ.
Показать варианты и ответ
- ✗Гарантирует отсутствие NullPointerException
- ✓Потокобезопасность без синхронизации и безопасное использование как ключа Map
- ✗Ускоряет операции, потому что объект хранится в стеке, а не в куче
- ✗Автоматически уменьшает память, переиспользуя все объекты программы
Что спросят дальше
- Почему immutable безопасен как ключ HashMap?
- Когда изменяемость всё же оправдана?
Разбор темы
- Проектирование неизменяемых классов
Зачем нужна неизменяемость, рецепт immutable-класса, защитные копии, безопасная публикация и records.
Связанные вопросы
Разбор собеседования с sotto
После собеседования sotto разбирает разговор: оценка, каждый вопрос — хорошо, частично или слабо, чего не хватило в ответе и над чем поработать к следующему разу. Первые 30 минут бесплатно.