1. 程式人生 > >內部類使用final關鍵字的理解

內部類使用final關鍵字的理解

(1).內部類是外部類的一個成員,就像外部類的成員方法一樣,所以內部類有許可權訪問外部類的所有成員,包括private的。
(2).內部類不能訪問外部類方法中的區域性變數,除非變數是final的(一般發生在方法中定義的內部類)。這是因為區域性變數的生命週期原因。

class Outer{
    private int a;
    public class Inner{
        private int a;
        public void method(int a){
            a++;    //區域性變數
this.a++;    //Inner類變數
            Outer.this.a++;    //Outer類變數

        }
    }
}

一般做法是在Outer中寫一個返回Inner類物件的方法
public Inner getInner(){
    return new Inner();
}

在其他類中使用內部類:
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
或者 Outer.Inner inner = outer.getInner();

static內部類的使用:
Outer.Inner inner = new Outer.Inner();

(1).所謂“區域性內部類”就是在物件的方法成員內部定義的類。而方法中的類,訪問同一個方法中的區域性變數,卻必須要加上一個final。

(2).原因是編譯程式實現上的困難:內部類物件的生命週期會超過區域性變數的生命期。區域性變數的生命期:當該方法被呼叫時,該方法中的區域性變數在棧中被建立,當方法呼叫結束時,退棧,這些區域性變數全部死亡。而內部類物件生命期,與其它類一樣,當建立一個區域性內部類物件後,只有當沒有其它人再引用它時,它才能死亡。所以完全可能一個方法已呼叫結束(區域性變數已死亡),但該區域性類的物件仍然活著。即:區域性類的物件生命期會超過區域性變數。
(3).區域性內部類的物件訪問同一個方法中的區域性變數,那麼這就要求只要區域性內部類物件還活著,那麼棧中的那些它要訪問的區域性變數就不能“死亡”(否則:它都死了,還訪問個什麼呢?)。這就是說:區域性變數的生命期至少等於或大於區域性內部類物件的生命期。

(4).解決方法:區域性內部類的物件可以訪問同一個方法中被定義為final的區域性變數。定義為final後,編譯程式的實現方法:將所有的區域性內部類物件要訪問的final型區域性變數,都拷貝成為該內部類物件中的一個數據成員。這樣,即使棧中區域性變數(含final)已死亡,但由於它是final,其值永不變,因而區域性內部類物件在變數死亡後,照樣可以訪問final型區域性變數。
(5).歸納總結:區域性內部類物件中包含有要訪問的final型區域性變數的一個拷貝,成為它的資料成員。因此,正是在這個意義上,final型區域性變數的生命期,超過其方法的一次呼叫。嚴格來說,方法呼叫結束,所有的區域性變數(含final)全死亡了。但:區域性內部類物件中有final型區域性變數的拷貝。