Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java local variable visibility in anonymous inner classes - why is 'final' keyword required?

Tags:

I don't understand why I cannot always access a variable from inside a 'listener' or 'handler'.

This is my code:

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

The only way is to declare it using the final keyword:

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

Why do I need to declare a variable final to gain access inside an event?

like image 408
stighy Avatar asked Sep 14 '11 21:09

stighy


People also ask

Why local variables should be final?

final is the only allowed access modifier for local variables. final local variable is not required to be initialized during declaration. final local variable allows compiler to generate an optimized code. final local variable can be used by anonymous inner class or in anonymous methods.

Can anonymous class access local variable?

An anonymous class cannot access local variables in its enclosing scope that are not declared as final or effectively final. Like a nested class, a declaration of a type (such as a variable) in an anonymous class shadows any other declarations in the enclosing scope that have the same name.

Can we use Non final local variables inside a local inner class?

A local inner class cannot be instantiated from outside the block where it is created in. Till JDK 7, the Local inner class can access only the final local variable of the enclosing block. However, From JDK 8, it is possible to access the non-final local variable of enclosing block in the local inner class.

What is the visibility of a local variable if created inside a method?

When we create a local variable inside a method, constructor, or block, its scope only remains within the method, block, or constructor. They are visible only within the method, constructor, or block. As you exit from the method or block, then the scope of a local variable is destroyed. 2.


2 Answers

Your SelectionAdapter is an anonymous inner class and I think this makes it clear:

Local classes can most definitely reference instance variables. The reason they cannot reference non final local variables is because the local class instance can remain in memory after the method returns. When the method returns the local variables go out of scope, so a copy of them is needed. If the variables weren’t final then the copy of the variable in the method could change, while the copy in the local class didn’t, so they’d be out of synch.

Anonymous inner classes require final variables because of the way they are implemented in Java. An anonymous inner class (AIC) uses local variables by creating a private instance field which holds a copy of the value of the local variable. The inner class isn’t actually using the local variable, but a copy. It should be fairly obvious at this point that a “Bad Thing”™ can happen if either the original value or the copied value changes; there will be some unexpected data synchronization problems. In order to prevent this kind of problem, Java requires you to mark local variables that will be used by the AIC as final (i.e., unchangeable). This guarantees that the inner class’ copies of local variables will always match the actual values.

like image 61
user219882 Avatar answered Sep 28 '22 19:09

user219882


I believe that Tom is saying is that if you could use local variables in an anonymous class then which button should it enable in the following code segment.

    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 ; 

The makers of java wanted to avoid that debate by requiring local variables used in anonymous classes to be final.

like image 34
emory Avatar answered Sep 28 '22 19:09

emory