2010-05-04 2 views
2

Привет, я просматривал книгу SCJP о внутренних классах и нашел это утверждение, это похоже на это.метод локальных внутренних классов, обращающихся к локальным переменным метода

Способ локальный класс может относиться только к локальным переменным, которые отмечены final

и в объяснении причины Указан о масштабах и времени жизни локального объекта класса и локальных переменных на куча, но я не могу этого понять. Я что-то пропустил здесь final ??

ответ

6

Причина в том, что при создании экземпляра локального класса метода все локальные переменные метода, на которые он ссылается, фактически копируются в него компилятором. Вот почему доступны только переменные final. A final переменная или ссылка неизменяема, поэтому она остается в синхронизации с ее копией внутри локального объекта метода. Если это не так, исходное значение/ссылка может быть изменена после создания локального класса метода, уступая место запутанному поведению и тонким ошибкам.

Рассмотрим следующий пример из JavaSpecialist newsletter no. 25:

public class Access1 { 
    public void f() { 
    final int i = 3; 
    Runnable runnable = new Runnable() { 
    public void run() { 
     System.out.println(i); 
    } 
    }; 
    } 
} 

Компилятор превращает внутренний класс в этом:

class Access1$1 implements Runnable { 
    Access1$1(Access1 access1) { 
    this$0 = access1; 
    } 
    public void run() { 
    System.out.println(3); 
    } 
    private final Access1 this$0; 
} 

Поскольку значение i является окончательным, компилятор может "встроенный" это во внутренний класс.

+0

Спасибо за четкое объяснение и thx для ссылки на информационный бюллетень .. это очень полезно. – flash

2

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

Когда экземпляр внутреннего класса создается, все ссылки на локальные переменные, которые он использует, копируются и передаются как неявные параметры конструктора (проверьте байт-код). На самом деле компилятор мог позволить сделать ссылки неконфиденциальными, но это было бы сбивать с толку, поскольку было бы непонятно, что произойдет, если метод изменяет ссылки после создания.

Однако создание контрольного финала не устраняет все проблемы. Хотя ссылка является неизменной, объект, стоящий за ссылкой, может по-прежнему быть изменчивым. Любые мутации объекта, созданного между созданием внутреннего класса до его активации, будут рассматриваться внутренним классом, а иногда это не намерение программиста.

Смежные вопросы