The reason is, when the method local class instance is created, all the method local variables it refers to are actually copied into it by the compiler. That is why only final
variables can be accessed. A final
variable or reference is immutable, so it stays in sync with its copy within the method local object. Were it not so, the original value / reference could be changed after the creation of the method local class, giving way to confusing behaviour and subtle bugs.
Consider this example from the 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);
}
};
}
}
The compiler turns the inner class into this:
class Access1$1 implements Runnable {
Access1$1(Access1 access1) {
this$0 = access1;
}
public void run() {
System.out.println(3);
}
private final Access1 this$0;
}
Since the value of i
is final, the compiler can "inline" it into the inner class.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…