1. 程式人生 > >《java程式設計思想系列之7》 內部類

《java程式設計思想系列之7》 內部類

一、建立內部類 內部類:可以將一個類的定義放在另一個類的定義內部 內部類和組合是完全不同的概念 如果想從外部類的非靜態方法之外的任意位置建立某個內部類的物件,那麼必須像在main()方法中那樣,具體的指明這個物件的型別:OuterClassName.InnerClassName. 二、連結到外部類 內部類自動擁有對其外圍類的所有成員的訪問許可權: 當某個外圍類的物件建立了一個內部類物件的時候,此內部類物件必定會咪咪的捕獲一個指向那個外圍類物件的引用。然後,當你訪問此外圍類的成員的時候,就是用那個引用來選擇外圍類的成員。幸運的時候,編譯器會幫助你處理所有的細節,但是你現在可以看到:內部類的物件只能在與其外圍類的物件相連的時候才能被建立(在內部類是非static類時候)。構件內部類物件的時候,需要一個指向外圍類的引用,如果編譯器訪問不到這個引用就會出錯。 三、使用.this和.new
想要直接建立內部類的物件,你不能按照你想象的方式,去引用外部類的名字DotNew,而是必須使用外部類的物件來建立該內部類物件。 在擁有外部類物件之前是不可能建立內部類物件的,這是因為內部類物件會暗暗的連線到建立它的外部類的物件上。但是,如果你建立是巢狀類(靜態內部類),那麼它就不需要對外部類物件的引用。 四、內部類與向上轉型 當將內部類向上轉型為其基類,尤其是轉型為一個介面的時候,內部類就有了用武之地。(從實現了某個介面的物件,得到此介面的引用,與向上轉型為這個物件的基類,實質上是一樣的)。這是因為內部類---某個介面的實現---能夠完全不可見,並且不可用。所得到的只是指向基類或者介面的引用,所以能夠很方便的隱藏實現細節。 五、在方法和作用域內的內部類
TrackingSlip類被嵌入if 語句的作用域內,這並不是說該類的建立是有條件的,它其實與別的類一起編譯過了。然而,在定義TrackingSlip的作用域之外,它是不可用的,除此之外,它與普通的類一樣。 六、匿名內部類 這種奇怪的語法指的是:建立一個繼承自Contents的匿名類的物件。 如果定義一個匿名內部類,並且希望它使用一個在其外部定義的物件,那麼編譯器就會要求其引數引用是final的,就像你在destination()的引數中看到的那樣。如果你忘記了,將會得到一個編譯時錯誤資訊: 匿名內部類與正規的繼承相比有些限制,因為匿名內部類既可以擴充套件類,也可以實現介面,但是不能兩者兼備。而且如果是實現介面,也只能實現一個介面。
內部類實現工廠模式 七、巢狀類 巢狀類:如果不需要內部類物件與其外圍類物件之間有聯絡,那麼可將內部類宣告為static。 1)要建立巢狀類的物件,並不需要其外圍類的物件 2)不能從巢狀類的物件中訪問非靜態的外圍類物件 3)普通的內部類不能有static資料和static欄位,也不能包含巢狀類。但是巢狀類可以包含所有這些東西 1、介面內部的類 正常情況下,不能在介面內部放置任何程式碼,但是巢狀類可以作為介面的一部分。你放到介面中的任何類都自動的是public和static的。因為類是static的,只是將巢狀類置於介面的名稱空間內,這並不違反介面的規則。你甚至可以在內部類中實現其外圍介面: 使用巢狀類類測試程式碼 2、從多層巢狀類中訪問外部類的成員 一個內部類被潛逃多少層並不重要-----它能夠透明的訪問所有它所嵌入的外圍類的所有成員。 八、為什麼需要內部類 每個內部類都能獨立的繼承自一個(介面的)實現,所以無論外圍類是否已經繼承類某個(介面的)實現,對於內部類都沒有影響。 內部類有效的實現了“多重繼承” 1)內部類可以有多個例項,每個例項都有自己得狀態資訊,並且與其外圍類物件的資訊相互獨立 2)在單個外圍類中,可以讓多個內部類以不同的方式實現同一介面,或繼承同一個類 3)建立內部類物件的時刻並不依賴於外圍類物件的建立 4)內部類並沒有令人迷惑的“is-a”關係,它就是一個獨立的實體。 九、內部類的繼承 因為內部類的構造器必須連線到指向其外圍類物件的引用,所以在繼承內部類的時候,事情會變得有點複雜。問題在於,那個指向外圍類的物件的“祕密的”引用必須被初始化,二在匯出類中不再存在可連線的預設物件。要解決這個問題,必須使用特殊的語法來明確的說清它們之間的關聯: 10、內部類可以被覆蓋嗎 預設的構造器是編譯器自動生成的,這裡是呼叫基類的預設構造器。這個例子說明,當繼承了某個外圍類的時候,內部類並沒有發生什麼特別神奇的變化。這兩個內部類是完全獨立的兩個實體,各自在自己得名稱空間內: 當然,明確的繼承某個內部類也是可以的: 11、區域性內部類 使用區域性內部類而不是使用匿名 內部類的理由就是: 1)我們需要一個已命名的構造器,或者需要過載構造器,而匿名內部類只能用於例項初始化 2)需要不止一個該內部類的物件 12、內部類識別符號 如果內部類是匿名的,編譯器會簡單的產生一個數字作為其識別符號。如果內部類是巢狀在別的內部類之中,只需要直接將他們的名字加上其外圍類識別符號與“$”的後面: