Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why should my local variables be final to be accessible from anonymous class? [duplicate]

Tags:

java

Possible Duplicate:
Cannot refer to a non-final variable inside an inner class defined in a different method

What is the reason behind the rule of having local variables declared as final in order to access them from anonymous class?

like image 933
Eugene Avatar asked Jan 24 '11 17:01

Eugene


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.

Why did we have to make some variables final or effectively final when using them in an anonymous class?

Forcing the variable to be final avoids giving the impression that incrementing start inside the lambda could actually modify the start method parameter.

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 a local class have access to non final local variables Why?

Accessing Members of an Enclosing Class In addition, a local class has access to local variables. However, a local class can only access local variables that are declared final.


3 Answers

When you access a final variable from an anonymous class, the compiler secretly copies their value into a member variable of the anonymous class. eg:

Runnable foo() {
  final int x = 42;
  return new Runnable() {
    void run() {
      System.out.writeln(x);
    }
  };
}

becomes:

// the actual name is generally illegal in normal java syntax
class internal_Runnable implements Runnable {
  final int x;
  internal_Runnable(int _x) { x = _x; }
  void run() {
    System.out.writeln(x);
  }
}

void foo() {
  final x = 42;
  return new internal_Runnable(x);
}

If the variable were not final and were allowed to change, the value cached in the anonymous class instance could go out of sync. This could have been avoided by use of a closure - that is, an object holding the values of all local variables, that both the original function and the new anonymous class instance access. .NET uses closures, for example. However, this can incur a performance hit, and perhaps for that reason, the Java language designers decided not to support full closures.

like image 169
bdonlan Avatar answered Sep 23 '22 02:09

bdonlan


...when an object of the anonymous class is instantiated, copies of the final local variables and method parameters referred to by the object's methods are stored as instance variables in the object. The methods in the object of the anonymous class really access those hidden instance variables.

Thus, the local variables and method parameters accessed by the methods of the local class must be declared final to prevent their values from changing after the object is instantiated.

From here.

like image 26
Jonathon Faust Avatar answered Sep 20 '22 02:09

Jonathon Faust


An anonymous class is a separate class. It has no access to the control flow inside your method. If you would reassign the variable in the anonymous class, you would actually only reassign the anonymous class' copy of the variable. That would be very error-prone, and hence the design choice was made to make it an error.

If you want to work around that, use an AtomicReference.

like image 29
Sean Patrick Floyd Avatar answered Sep 21 '22 02:09

Sean Patrick Floyd