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

Eug*_*ene 9 java

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

为了从匿名类访问局部变量,将局部变量声明为final的规则是什么原因?

Jon*_*ust 8

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

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

这里开始.


bdo*_*lan 7

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

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

变为:

// 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);
}
Run Code Online (Sandbox Code Playgroud)

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