局部内部类为什么只能访问final局部变量,对于成员变量却可以随便访问?
public class OuterClass { private int memberField = 10; public void outerDo(){ final int localField = fromOther(); class InnerClass{ public void innerDo(){ memberField = localField; } }; } private int fromOther() { return 20; } }
局部变量和成员变量对于内部类而言,具有一定的共性,都是该内部类外面的变量。如果要求内部类只能访问final的局部变量是为了确保局部变量不被修改的话,那么内部类访问成员变量应该也有类似的限制才对
我认为是由于他们的存活范围导致了这个区别:
首先内部类的实例可以在方法结束后依然存活,局部变量在方法结束后却无法存活,所以在内部类中无法访问NON-final的局部变量;
类在堆内存中,而变量在栈内存中,所以可能出现变量会回收的情况。
而成员变量的存活时间是取决于外部类的实例的,内部类实例中都会引用当前外部类实例,所以他们拥有一致的生命周期,于是可以访问成员变量。
剩下的问题是,为什么可以访问final的局部变量呢?
如果将一个访问了final的局部变量的内部类进行反编译,可以发现该变量是被作为构造函数的参数传入进去的,与之一起传入的参数还有外部类实例
......
com.study.innerclass.OuterClass$1InnerClass(com.study.innerclass.OuterClass, int);
Code:
Stack=2, Locals=3, Args_size=3
0: aload_0
1: aload_1
2: putfield #12; //Field this$0:Lcom/study/innerclass/OuterClass;
5: aload_0
6: iload_2
7: putfield #14; //Field val$localField:I
10: aload_0
11: invokespecial #16; //Method java/lang/Object."<init>":()V
14: return
LineNumberTable:
line 9: 0
LocalVariableTable:
Start Length Slot Name Signature
0 15 0 this Lcom/study/innerclass/OuterClass$1InnerClass;
既然javac是这样处理内部类的,那么这与为内部类提供一个带参数的构造函数就没什么两样了!
public class OuterClass { private int memberField = 10; public void outerDo(){ int localField = fromOther(); class InnerClass{ private int local; public InnerClass(int local) { this.local = local; } public void innerDo(){ memberField = this.local; } }; new InnerClass(localField); } private int fromOther() { return 20; } }