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

时间:2011-01-24 17:33:09

标签: java

  

可能重复:
  Cannot refer to a non-final variable inside an inner class defined in a different method

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

4 个答案:

答案 0 :(得分:8)

  

...当一个对象的时候   匿名类被实例化,   最终局部变量的副本   和引用的方法参数   对象的方法存储为   对象中的实例变量。该   匿名对象中的方法   类真的访问那些隐藏的   实例变量。

     因此,当地   变量和方法参数   通过本地方法访问   必须将类声明为final   防止他们的价值观发生变化   实例化对象后。

来自here

答案 1 :(得分:7)

当您从匿名类访问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 uses closures, for example.然而,这可能会导致性能损失,也许正是因为这个原因,Java语言设计者决定不支持完全关闭。

答案 2 :(得分:1)

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

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

答案 3 :(得分:0)

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