Я не понимаю, почему я не могу всегда получить доступ к переменной изнутри «слушателя» или "обработчик".
Это мой код:
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 , чтобы получить доступ внутри события?
Я считаю, что Том говорит, что если вы можете использовать локальные переменные в анонимном классе, то какую кнопку следует включить в следующем фрагменте кода.
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 хотели избежать этой дискуссии, требуя, чтобы локальные переменные, используемые в анонимных классах, были окончательными.
Вероятно, это не оптимальный выбор дизайна. В 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 не боялась многословия, если нужна ясность.