Вопрос о локальной финальной переменной в Java - PullRequest
8 голосов
/ 10 мая 2011

У меня есть следующий код:

public class BookLib {
    void f() {
        final int x = 5; // Line 1
        class MyCLass {
            void print() {
                System.out.println(x);
            }
        }
    }
}

Я не понимаю, почему в этом случае следует использовать конечную переменную (строка 1)?

Ответы [ 4 ]

20 голосов
/ 10 мая 2011

Вы создали внутренний класс здесь.Поскольку время жизни объектов этого класса потенциально может быть намного больше времени выполнения вызова метода (т. Е. Объект может существовать еще долго после возврата метода), ему необходимо «сохранить» состояние локальных переменных, которое онможет получить доступ.

Это сохранение выполняется путем создания (невидимой, синтетической) копии внутри внутреннего класса и автоматической замены всех ссылок на локальную переменную ссылками на эту копию.Это может привести к странным эффектам, когда локальная переменная была изменена после создания объекта внутреннего класса.

Чтобы избежать этого, существует требование, чтобы все локальные переменные, к которым вы обращаетесь таким образом, былиfinal: это гарантирует, что существует только одно возможное значение для локальной переменной, и несоответствия не наблюдаются.

Это конкретное правило можно найти в §8.1.3 Внутренние классы и вложенные экземпляры из JLS :

Любая локальная переменная, параметр формального метода или параметр обработчика исключений, используемые, но не объявленные во внутреннем классе, должны быть объявлены как окончательные.Любая локальная переменная, используемая, но не объявленная во внутреннем классе, должна быть определенно назначена (§16) перед телом внутреннего класса.

3 голосов
/ 10 мая 2011

Здесь вы создаете внутренний класс.Чтобы получить доступ к контексту выполнения, ссылки на переменные должны оставаться неизменными, в противном случае наблюдается поведение ошибки.Чтобы гарантировать это, вы должны объявить вашу переменную final: таким образом, ее нельзя изменить.

См. Подробное объяснение здесь .

1 голос
/ 10 мая 2011

Из книги Кэти Сьерра Скип

Локальные переменные метода живут в стеке и существуют только в течение времени жизни метода. Мы уже знаем, что область действия локальной переменной ограничена методом, в котором объявлена ​​переменная. Когда метод заканчивается, стековый фрейм уничтожается и переменная становится историей. Но даже после завершения метода внутренний объект класса, созданный в нем, может оставаться в куче, если, например, ссылка на него была передана в некоторый другой код, а затем сохранена в переменной экземпляра. Поскольку локальные переменные не гарантируются живыми до тех пор, пока объект внутреннего класса метода локальный, объект внутреннего класса не может их использовать. Если только локальные переменные не помечены как окончательные!

0 голосов
/ 10 мая 2011

Итак, у вас есть локальная конечная переменная и метод локального внутреннего класса. Внутренний класс локального метода не может использовать неконечные переменные, объявленные в методе (включая параметры).

Чтобы углубиться в это: Внутренний класс, локальный для метода, может быть создан только внутри метода, в котором этот класс определен. Локальные переменные живут в стеке в течение всего времени жизни метода. Когда метод завершается, локальные переменные исчезают, однако созданный объект внутреннего класса все еще живет.

Это вопрос времени жизни / объема.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...