2010-05-04 239 views
2

您好我正在阅读关于内部类的SCJP书,并发现这个语句,它是这样的。方法本地内部类访问方法的局部变量

的方法,局部类只能引用被标记final

,并在解释中指定的原因是关于局部类对象的范围和寿命和局部变量上的局部变量堆,但我无法理解这一点。我在这里丢失了什么关于final ??

回答

6

原因是,当创建方法局部类实例时,它所引用的所有方法局部变量实际上都被编译器复制到其中。这就是为什么只有final变量可以被访问。 A final变量或引用是不可变的,所以它与方法本地对象内的副本保持同步。如果不是这样,那么在创建方法本地类之后,原始值/引用可能会改变,让位于混淆行为和微妙的错误。

考虑从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); 
    } 
    }; 
    } 
} 

编译器接通内部类成这样:

class Access1$1 implements Runnable { 
    Access1$1(Access1 access1) { 
    this$0 = access1; 
    } 
    public void run() { 
    System.out.println(3); 
    } 
    private final Access1 this$0; 
} 

由于i值是最后时,编译器可以 “内联”它进入了内心阶层。

+0

感谢您对通讯链接的明确解释和thx ..这是非常有帮助的。 – flash 2010-05-04 09:24:43

2

正如我所见,从方法本地类(例如匿名类)访问局部变量是一件有风险的事情。这是编译器允许的,但它需要很好地理解发生了什么。

当内部类被实例化时,它所使用的所有对局部变量的引用都被复制,并作为隐含的构造函数参数(检查字节码)传递。实际上,编译器可以允许使引用不是最终的,但这会让人困惑,因为如果方法在实例化之后改变引用将会发生什么,这并不清楚。

但是,制作参考最终并不能消除所有问题。尽管引用是不可变的,但引用背后的对象仍然可以是可变的。内部类的实例化到内部类的任何突变都会被内部类看到,有时这不是程序员的意图。