方法调用的局部变量(
final内部类必须可以访问)和实例的私有数据成员之间有很大的区别。
内部类可以访问包含的实例,也可以访问该实例的所有成员
final。不需要将它们定型,因为(在您的情况下)已通过引用它们
Foo.this。因此,在访问您的
i成员时,内部类实际上是在访问
Foo.this.i,只是如果引用没有它,就可以隐含
Foo.this(如
this)。
但是匿名类的代码无法以这种方式访问局部变量,因为它们(当然)不是包含类的实例成员。因此,相反,编译器做了一件非常有趣的事情:为每个局部变量创建 匿名
类的实例成员
final,并在创建匿名类的实例时,使用局部变量的值初始化这些成员。
让我们看一下它:
public class InnerEx { public static final void main(String[] args) { new InnerEx().test("hi"); } private void test(String arg) { final String localVar = arg; Runnable r = new Runnable() { public void run() { System.out.println(localVar); } }; r.run(); }}
编译后,我们得到
InnerEx.class和
InnerEx.class。如果我们反编译
InnerEx.class,我们将看到:
class InnerEx implements java.lang.Runnable { final java.lang.String val$localVar; final InnerEx thisval$localVar; InnerEx(InnerEx, java.lang.String); Code: 0: aload_0 1: aload_1 2: putfield #1 // Field thisInnerEx#test:LInnerEx; 5: aload_0 6: aload_2 7: putfield #2 // Field val$localVar:Ljava/lang/String; 10: aload_0 11: invokespecial #3 // Method java/lang/Object."<init>":()V 14: return public void run(); Code: 0: getstatic #4 // Field java/lang/System.out:Ljava/io/PrintStream; 3: aload_0 4: getfield #2 // Field val$localVar:Ljava/lang/String; 7: invokevirtual #5 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 10: return }
请注意,实例成员名为,这是为代表调用中的局部变量而创建的实例成员。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)