为什么我的局部变量最终可以从匿名类访问?

可能重复:
不能引用在不同方法中定义的内部类中的非final变量

将局部变量声明为final以便从匿名类访问它们的原因是什么?

当您从匿名类访问final变量时,编译器会将其值秘密地复制到匿名类的成员变量中。 例如:

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

变为:

 // 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); } 

如果变量不是final并且允许更改,则匿名类实例中缓存的值可能会不同步。 这可以通过使用闭包来避免 – 也就是说,一个包含所有局部变量值的对象,原始函数和新的匿名类实例都可以访问。 例如,.NET使用闭包。 但是,这可能会导致性能损失,也许由于这个原因,Java语言设计者决定不支持完全关闭。

…当实例化匿名类的对象时,对象方法引用的最终局部变量和方法参数的副本将作为实例变量存储在对象中。 匿名类的对象中的方法确实访问那些隐藏的实例变量。

因此,必须将本地类的方法访问的局部变量和方法参数声明为final,以防止在实例化对象后它们的值发生更改。

从这里开始 。

匿名类是一个单独的类。 它无法访问方法中的控制流。 如果要在匿名类中重新分配变量,实际上只会重新分配匿名类的变量副本。 这将非常容易出错,因此设计选择使其成为错误。

如果您想解决此问题,请使用AtomicReference

这是因为匿名内部对象可能会超出其上下文,如果它指的是非final变量,那么它就会让它与不再存在的事物进行对话。