Ответ
Модификатор final для переменной означает, что значение этой переменной может быть присвоено только один раз (при объявлении или в конструкторе/инициализаторе). После инициализации его нельзя изменить.
Типы final-переменных:
-
final-примитив: Значение становится константой.
final int MAX_USERS = 100; // MAX_USERS = 200; // Ошибка компиляции! -
final-ссылка на объект: Нельзя изменить саму ссылку, но состояние объекта может меняться.
final List<String> names = new ArrayList<>(); names.add("Алиса"); // Можно: изменяем состояние объекта // names = new LinkedList<>(); // Ошибка: нельзя переприсвоить ссылку
Особенности инициализации:
- Поле класса: Должно быть инициализировано к моменту завершения работы каждого конструктора.
- Статическое final-поле (константа): Должно быть инициализировано при объявлении или в статическом блоке.
- Локальная переменная: Должна быть инициализирована до первого использования.
Практическое применение:
- Создание констант (
public static final). - Гарантия, что ссылка на объект, переданная в метод, не будет заменена внутри метода.
- Использование в анонимных классах для доступа к локальным переменным (они должны быть final или effectively final).
Ответ 18+ 🔞
Да ты посмотри, какая интересная хуйня, этот final! Ну, в смысле, модификатор такой. Представь себе — ты объявил переменную и прикрутил к ней этот самый final, и всё, пиши пропало. Значение ей можно дать ровно один раз, как первую и последнюю зарплату. Дальше хоть тресни — не переприсвоишь.
Ну и какие они бывают, эти final-переменные:
-
Примитив final'ный. Всё, константа, точка. Запомнил число и носи его с собой.
final int MAX_USERS = 100; // MAX_USERS = 200; // Ёпта, компилятор тебе мозги выест! Нельзя! -
Ссылка final'ная. Вот тут, блядь, тонкий момент, многие об него запнутся. Саму ссылку — ту самую, которая на объект указывает — менять низя. А вот внутрь объекта залезть и там всё перевернуть — пожалуйста, на здоровье!
final List<String> names = new ArrayList<>(); names.add("Алиса"); // Можно! Состояние объекта меняем, ссылка та же. // names = new LinkedList<>(); // А вот это уже пиздец, ошибка! Куда ссылку понес, мудак?
А теперь, сука, про инициализацию, чтоб ты понимал, где подвох:
- Поле в классе. Его нужно проинициализировать так, чтобы к моменту, когда конструктор свою работу заканчивает, всё было готово. В каждом конструкторе, блядь!
- Статическое final-поле (она же константа). Вообще красота. Инициализируй при объявлении, либо в статическом блоке — и спи спокойно.
- Локальная переменная. Проще простого: инициализируй до того, как в первый раз использовать собрался. Не инициализируешь — получишь по ебалу от компилятора.
И где это, блядь, применять-то?
- Константы делать, самые что ни на есть
public static final. - Чтобы в метод передать объект и быть уверенным, что тебе внутри метода ссылку не подменят на какую-нибудь левую хуйню.
- В анонимных классах, эти твои, чтобы к локальным переменным из внешнего метода достучаться — они должны быть
finalили effectively final, иначе нихуя не получится. Вот такая, блядь, магия!