Java 內部類

Java中實現內部類

Java 內部類

內部類相信大家都用過很多次了,就不說它是怎麼用的了。

內部類

1.成員內部類

Java 內部類

需要注意的是, 當成員內部類擁有和外部類同名的成員變量或這方法時, 默認情況下訪問的是內部類的成員, 如要訪問外部類的同名成員, 需要使用以下形式:

外部類.this.成員變量
外部類.this.成員方法

內部類是依附外部類而存在的, 也就是說要創建成員內部類的對象,前提是創建一個外部類的對象,創建成員內部類的方式如下:

new Main().new Inner();

成員內部類可以擁有private訪問權限、protected訪問權限、public訪問權限、默認訪問權限。如用private修飾,則只能在外部類的內部訪問。

2.局部內部類

局部內部類是定義在一個方法或作用域中的類,它的訪問權限僅限於方法內或作用域內。

Java 內部類

局部內部類也可以返回,像這樣:

Java 內部類

3.匿名內部類

匿名內部類應該是我們平常使用最多的了,如下面創建線程:

Java 內部類

匿名內部類在編譯的時候有系統自動起名:Main$1

匿名內部類是沒有構造器的類,大部分用於繼承其他類或實現接口,並不需要增加額外的方法,只是對繼承方法的實現或是重寫

4.靜態內部類

靜態內部類也是定義在另一個類裡面的類,只不過在類前加上了static。靜態內部類是不需要依賴於外部類的,與靜態成員變量類似。

Java 內部類

外部創建該靜態類時可以如下創建:

Main.Inner mi = new Main Inner();

內部類實現原理

內部類為什麼能夠訪問外部類的成員?

定義內部類如下:

Java 內部類

使用javap命令進行反編譯。

編譯後得到Main.class Main$Inner.class兩個文件,反編譯Main$Inner.class文件如下:

Java 內部類

可以看到,內部類其實擁有外部類的一個引用,在構造函數中將外部類的引用傳遞進來。

匿名內部類為什麼只能訪問局部的final變量?

其實可以這樣想,當方法執行完畢後,局部變量的生命週期就結束了,而局部內部類對象的生命週期可能還沒有結束,那麼在局部內部類中訪問局部變量就不可能了,所以將局部變量改為final,改變其生命週期。

編寫代碼如下:

Java 內部類

這段代碼編譯為Main.class Main$1.class兩個文件,反編譯Main$1.class文件如下:

Java 內部類

可以看到,java將編譯時已經確定的值直接複製,進行替換,將無法確定的值放到了內部類的常量池中,並在構造函數中將其從常量池取出到字段中。

可以看出,java將局部變量m直接進行復制,所以其並不是原來的值,若在內部類中將m更改,局部變量的m值不會變,就會出現數據不一致,所以java就將其限制為final,使其不能進行更改,這樣數據不一致的問題就解決了。

匿名內部類為什麼訪問外部類成員字段不用final?

上面說了,final關鍵字是為了解決數據不一致的問題,因為內部類中存有外部類的引用,所有對外部類中字段的修改都會真實的反映到外部類實例本身,所以不需要用final來修飾。


分享到:


相關文章: