Можно ли изменить final поле класса в private сеттере?

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

Ответ

Нет, изменить final поле после инициализации невозможно, даже в private сеттере. Модификатор final гарантирует, что поле будет присвоено ровно один раз.

Правила инициализации final полей:

  1. При объявлении:
    private final int VALUE = 10;
  2. В конструкторе (или блоке инициализации):

    public class MyClass {
    private final int value;
    
    public MyClass(int value) {
        this.value = value; // Единственное присваивание
    }
    }

Пример ошибки:

public class Example {
    private final int immutableValue;

    public Example(int value) {
        this.immutableValue = value;
    }

    // Этот метод НЕ скомпилируется:
    private void setImmutableValue(int newValue) {
        this.immutableValue = newValue; // Ошибка компиляции:
        // "cannot assign a value to final variable immutableValue"
    }
}

Почему это важно?

  • Безопасность потоков: final поля гарантированно видны другим потокам после завершения конструктора (гарантии Java Memory Model).
  • Неизменяемость: Ключевой принцип для создания immutable-объектов, что упрощает reasoning и избегает side effects.
  • Оптимизация: JVM может агрессивно кэшировать и оптимизировать доступ к final полям.

Альтернатива: Если нужно "изменяемое" final-поле, используйте обертку (например, AtomicReference), но сама ссылка останется final.