Гарантирует ли ключевое слово final в Java, что класс является полностью иммутабельным?

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

Ответ

Нет. Объявление класса как final лишь запрещает его наследование, но не гарантирует иммутабельности (неизменяемости состояния его объектов).

Критерии иммутабельного класса:

  1. final класс (чтобы нельзя было создать изменяемый подкласс).
  2. Все поля объявлены как private final (инициализируются только в конструкторе).
  3. Отсутствие сеттеров (setter методов), изменяющих состояние.
  4. Защищённое копирование (defensive copying) для mutable-полей: если класс содержит ссылки на изменяемые объекты (например, массивы, коллекции), их необходимо копировать при передаче в конструктор и при возврате через геттер.

Пример иммутабельного класса:

public final class ImmutablePoint {
    private final int x;
    private final int y;

    public ImmutablePoint(int x, int y) {
        this.x = x;
        this.y = y;
    }
    // Только геттеры, возвращающие примитивы (или копии mutable-объектов)
    public int getX() { return x; }
    public int getY() { return y; }
}

Класс, объявленный как final, но имеющий публичные сеттеры или изменяемые поля, не будет иммутабельным.