區域性內部類為什麼只能訪問final區域性變數,對於成員變數卻可以隨便訪問?
區域性內部類為什麼只能訪問final區域性變數,對於成員變數卻可以隨便訪問?
http://kingquake21.iteye.com/blog/1033436部落格分類: Java innerclass inner final
區域性內部類為什麼只能訪問final區域性變數,對於成員變數卻可以隨便訪問?
Java程式碼- 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是這樣處理內部類的,那麼這與為內部類提供一個帶引數的建構函式就沒什麼兩樣了!
Java程式碼- 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;
- }
- }