Ключевое слово final

Смысл final зависит от места объявления.

ГдеЧто запрещено
переменная/полеповторное присваивание после инициализации
параметрприсваивание нового значения внутри метода
методпереопределение в наследнике
класснаследование от класса
final class Price {
    private final BigDecimal amount;
 
    Price(BigDecimal amount) {
        this.amount = amount;
    }
}
 
final List<String> items = new ArrayList<>();
items.add("book"); // допустимо
// items = List.of(); // нельзя переназначить ссылку

Blank final и константы

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

Только compile-time константы подставляются компилятором в клиентский байткод. Если изменить такую константу в библиотеке, клиент желательно перекомпилировать.

Модель памяти

Для корректно сконструированного объекта Java Memory Model даёт специальные гарантии видимости final-полей. Гарантия может быть нарушена плохим проектированием, если this «утёк» до окончания конструктора. Она не делает потокобезопасными объекты, на которые ссылается поле.

Ограничения

  • final не означает immutable;
  • final-метод всё ещё может быть перегружен;
  • private-метод фактически не переопределяется, поэтому final для него избыточен;
  • локальная final-переменная должна быть определённо присвоена до чтения.

На собеседовании

Можно ли изменить объект через final-ссылку? Да, если сам объект изменяем.

Чем final-метод отличается от static? Первый участвует в динамическом вызове, но запрещает переопределение; второй выбирается статически.

Можно ли присвоить blank final в каждом конструкторе? Да, ровно один раз на каждом пути.

Зачем финальные поля immutable-классу? Они фиксируют ссылки/значения и дают дополнительные гарантии публикации.

Связано: Immutable классы и данные, Java Memory Model.