Карта / Синтаксис и типы / Константы (final)

Константы (final)

final перед переменной значит «присвоить можно только один раз». После этого — переприсвоить нельзя, компилятор не даст:

final int MAX_USERS = 100;
MAX_USERS = 200;   // ❌ ошибка компиляции — final нельзя менять

Константы по конвенции называют ЗАГЛАВНЫМИ_БУКВАМИ_С_ПОДЧЁРКИВАНИЯМИ — так с первого взгляда видно: это значение зафиксировано и не должно меняться по ходу программы.

Копнуть глубже

final на объекте — это ловушка для новичков. final фиксирует ссылку, а не содержимое объекта:

final List<String> names = new ArrayList<>();
names.add("Артур");     // ✅ можно — содержимое объекта меняется
names = new ArrayList<>(); // ❌ нельзя — нельзя поменять саму ссылку

Сама переменная names навсегда указывает на один и тот же список. Но что происходит внутри этого списка — final не запрещает.

static final — это уже настоящая константа класса, одна на все объекты:

class Config {
    static final int MAX_USERS = 100;   // одна на весь класс
}
Под капотом

Blank final. Поле можно объявить final без значения сразу — но тогда обязан присвоить его ровно один раз в каждом конструкторе:

class User {
    final String id;
    User(String id) {
        this.id = id;   // присваивается один раз здесь
    }
}

final ≠ неизменяемость (immutable). Это разные вещи: final запрещает менять ссылку, а неизменяемость — это когда сам объект не даёт менять своё содержимое (как String). Объект может быть final-полем и при этом оставаться изменяемым (как ArrayList в примере выше) — и наоборот, можно создавать неизменяемые объекты без final.

🎤 Закрыл тему, если можешь объяснить:
• что делает `final` и почему константы пишут ЗАГЛАВНЫМИ;
• почему `final`-список можно менять изнутри, но не переприсвоить (если дошёл до 2-го слоя).