Видимость локальной переменной Java в анонимных внутренних классах - почему требуется ключевое слово final?

Я не понимаю, почему я не могу всегда получить доступ к переменной изнутри «слушателя» или "обработчик".

Это мой код:

Button btnDownload = new Button(myparent, SWT.NONE);
btnDownload.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                btnDownload.setEnabled(false); // I CAN'T 
            }
        });

Единственный способ - объявить его с помощью ключевого слова final :

final Button btnDownload = new Button(myparent, SWT.NONE);

Почему мне нужно объявлять переменную final , чтобы получить доступ внутри события?

24
задан Charles Goodwin 14 September 2011 в 22:30
поделиться

3 ответа

Я считаю, что Том говорит, что если вы можете использовать локальные переменные в анонимном классе, то какую кнопку следует включить в следующем фрагменте кода.

    Button btnDownload = new Button(myparent, SWT.NONE);
    btnDownload.addSelectionListener(new SelectionAdapter() {
                @Override
                public void widgetSelected(SelectionEvent e) {
                    btnDownload.setEnabled(false); // I CAN'T 
                }
            });
   btnDownload = new Button(somethingelse , SWT.NONE);
   btnDownload = null ;

Создатели Java хотели избежать этой дискуссии, требуя, чтобы локальные переменные, используемые в анонимных классах, были окончательными.

18
ответ дан 28 November 2019 в 22:46
поделиться

Вероятно, это не оптимальный выбор дизайна. В Java 8, наряду с лямбда-выражением, мы надеемся, что это требование final будет отменено.

Цель состоит в том, чтобы запретить присваивание локальной переменной из анонимного класса. Но это не требует маркировки локальной переменной как окончательной.

void f()

  Object var = ...;
  new Anon(){
      ...
      print(var); // reading is ok
      var = x;    // error, can't write to var            [1]
  }

Компилятор фактически создает копию var и сохраняет ее в анонимном классе. Анонимный класс получает доступ к копии только потом. Приведенный выше код фактически преобразуется в

void f()

  Object var = ...;
  new Anon$1(var);

class Anon$1
{
    final Object $var;
    Anon$1(Object var){ this.$var=var; }
    ...
    print($var); 
    $var = x;    // error, naturally                      [2]
}

. Как видите, нет технической причины требовать, чтобы var было окончательным. Все, что должен сделать компилятор, когда он встречает [2], зная, что $var является синтезированным полем для var, сообщает об ошибке «локальная переменная var не может быть назначена анонимным классом» (вместо «$ var is final») и не может быть назначен на ")

Разработчики языка решили нас раздражать, потребовав ключевое слово final для локальной переменной; Я не помню обоснование; в общем, Java не боялась многословия, если нужна ясность.

3
ответ дан 28 November 2019 в 22:46
поделиться
0
ответ дан 28 November 2019 в 22:46
поделиться
Другие вопросы по тегам:

Похожие вопросы: