Как создать иммутабельный (неизменяемый) класс в Java?

«Как создать иммутабельный (неизменяемый) класс в Java?» — вопрос из категории ООП, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Иммутабельный класс — это класс, экземпляры которого нельзя изменить после создания. Это ключевая концепция для написания потокобезопасного и предсказуемого кода.

Правила создания:

  1. Объявите класс как final — запрещает наследование и переопределение методов.
  2. Сделайте все поля private и final — гарантирует однократную инициализацию и скрывает состояние.
  3. Не предоставляйте сеттеров (setter methods).
  4. Инициализируйте все поля через конструктор.
  5. Защитите от "утечки ссылок" (defensive copying):
    • Для mutable-полей в конструкторе сохраняйте копию переданного объекта.
    • Для геттеров, возвращающих mutable-поля, возвращайте копию или неизменяемое представление.

Пример:

import java.util.*;

public final class ImmutablePerson {
    private final String name;
    private final Date birthDate; // mutable класс!
    private final List<String> hobbies;

    public ImmutablePerson(String name, Date birthDate, List<String> hobbies) {
        this.name = name;
        // Защитная копия для mutable-объекта
        this.birthDate = new Date(birthDate.getTime());
        // Защитная копия для коллекции
        this.hobbies = new ArrayList<>(hobbies);
    }

    public String getName() { return name; }

    public Date getBirthDate() {
        // Возвращаем копию, а не оригинальную ссылку
        return new Date(birthDate.getTime());
    }

    public List<String> getHobbies() {
        // Возвращаем неизменяемую обертку
        return Collections.unmodifiableList(new ArrayList<>(hobbies));
    }
}

Для удобного создания объектов со многими полями используйте паттерн Builder.