内部類:将一個類的定義放在另一個類的定義内部。内部類機制可以把邏輯相關的類組織在一起,并控制位于内部的類的可視性。
内部類與組合是完全不同的概念。
内部類不僅是一種代碼隐藏機制(将類置于其他類的内部),還能與外圍類通信。
類似于外圍類的成員的内部類。
内部類可以通路其外圍類的所有字段和方法(所有成員)。建立一個普通内部類對象需要先建立其外圍類的對象,然後使用該外圍類對象取建立内部類對象。當某個外圍類建立了一個内部類對象時,此内部類對象必定會秘密地捕獲一個指向那個外圍類對象的引用。然後就可使用這個引用來通路外圍類對象的成員。
運作結果為:
如果需要在内部類中擷取外圍類對象的引用,可以使用 外圍類名.this 來擷取
要直接建立普通内部類對象,必須使用外圍類的對象來建立該内部類對象。這也解決了内部類名字作用域的問題,即使用外圍類對象隻能建立定義在外圍類中的内部類的對象。
是以,就不必聲明(也不能聲明)外圍類的類名,如inner = dot.new DotNew.Inner();
在擁有外圍類對象之前是不可能建立内部類對象的。這是因為内部類對象會暗暗地連接配接到建立它的外圍類對象上。但是,如果你建立的是嵌套類(靜态内部類),那就不需要先建立外圍類對象。
先看一下内部類通路外圍類成員的方式:如果想要通路外圍類的某個成員,直接使用外圍類這個成員的名字就可以。
但是,如果外圍類要通路内部類的成員的話就不能使用這種方式(即直接使用内部類成員的名字):
正确的方式應該先建立内部類的對象再通過此對象去通路:
内部類可以直接通過外圍類的成員名去通路外圍類成員,而外圍類需要通過内部類的對象去通路内部類成員。造成這種差别的原因可能是:
在使用内部類對象時,可保證其外圍類對象一定被建立了,且内部類對象一定有一個指向其外圍類對象的引用,是以内部類可以通過成員名直接通路(可能編譯器會在成員名前自動拼接 外圍類對象引用.);而在使用外部類對象時,并不能保證内部類對象一定被建立了,是以需要先建立内部類對象,然後通過這個内部類對象去通路内部類成員。
可以在一個方法裡面或在任意作用域(方法的作用域:if(isOk){作用域}、類的作用域)中定義内部類。這麼做有兩個理由:
在方法中實作了某個接口,可以建立并傳回對其的引用;
要解決一個複雜的問題,想要建立一個類來輔助你的解決方案,但是又不希望這個類是公共可用的。
在方法的作用域内(而不是在其他類的作用域内)建立一個完整的類,這被稱作局部内部類。
注意:
1.PDestination類是destination方法的一部分,而不是Parcel5的一部分。是以,在destination()之外不能通路PDestination;
2.在destination()方法中定義了内部類PDestination,并不意味着一旦destination()方法執行完畢,PDestination就不可用了。
TrackingSlip類被嵌入在if語句的作用域内,這并不是說該類本身的建立是有條件的,它其實會與其他類一起被編譯。然而,在定義TrackingSlip的作用域之外,它是不可用的;除此之外,它與普通類一樣。
return語句的含義為:建立一個實作(繼承)了Contents接口(類)的匿名類對象。
有非預設構造器的類Wrapping
匿名類Parcel8擴充Wrapping類
目前來看,定義匿名内部類的方式為:
1.當是 new 接口名()時,建立的就是一個實作類對象;
2.當是 new 基類名(基類構造器的參數)時,建立的是一個子類對象,但在建立子類對象中包含的基類對象時調用的就是new關鍵字後指定的基類構造器。
在匿名類中定義字段時,還能夠對其執行初始化操作。
如果定義一個匿名内部類,并且希望它使用一個在其外部定義的對象(可以是方法傳入的參數,也可以是外圍類的成員),那麼編譯器會要求這個對象是final的。
注:匿名内部類(子類)本身使用外部對象才要求是final的,但如果隻是基類使用而匿名内部類自身不使用,則不需要是final的。
上面的例子中的匿名内部類使用的在其外部定義的對象是通過方法的參數傳入的,也可以直接使用外圍類的成員(private成員預設是final的)。
匿名類因為沒有名字,是以不可能有構造器。
通過執行個體初始化(本質就是通過普通代碼塊),就能達到為匿名内部類建立一個構造器的效果。
匿名内部類與正規的繼承相比有些受限,因為匿名内部類既可以擴充類,也可以實作接口,但是不能兩者兼備。而且如果是實作接口,也隻能實作一個接口。
如果不需要内部類對象與其外圍類對象之間有聯系,那麼可以将内部類聲明為static。這通常稱之為嵌套類或者靜态内部類。
普通的内部類對象隐式地儲存了一個引用,指向它的外圍類對象。而嵌套類對象就沒有這個引用,這意味着:
要建立嵌套類對象,不需要其外圍類對象;
不能從嵌套類對象中通路非靜态的外圍類對象。
普通的内部類中不能有static資料和static字段,也不能包含嵌套類(也是static的),但是嵌套類可以包含這些靜态的東西。其原因可認為是:
普通内部類可看作是外圍類的非靜态成員,要求它的初始化必須在其外圍類對象建立之後進行。在建立内部類對象的時候,會先加載外圍類,再加載内部類。類加載完成後就會初始化類的靜态成員,如果内部類有靜态成員,那麼就會在類加載後初始化内部類的靜态成員,但這個時候其外圍類對象還未建立,這與要求沖突。是以不允許普通内部類包含靜态成員。
這個例子中還有一個需要注意的地方:外圍類能直接通路靜态内部類的靜态私有成員(構造器)。是以總結一下外圍内通路内部類的規律:
外圍類可通過建立内部類對象通路内部類的所有成員(包括私有成員);
外圍類可直接通路(構造器或者類名.靜态成員名)靜态内部類的所有靜态成員(包括私有靜态成員)。
接口中的變量預設是public static final的;
接口中的方法預設是public的;
接口中的類預設是public static的,也就是說,接口中的類預設是靜态内部類。