Java中的嵌套類、內部類、靜態內部類,java嵌套
在Java中我們在一個類的內部再定義一個類,如下所示:
class OuterClass { ... class NestedClass { ... }}
那麼在上面的例子中我們稱OuterClass為外圍類(enclosing class),裡面的那個類稱之為嵌套類(Nested Class).
嵌套類可以分為兩種,靜態和非靜態,即靜態嵌套類和非靜態嵌套類。非靜態嵌套類又叫做內部類(Inner Class)。我們通常所說的靜態內部類其實是不嚴格的,嚴格的說應該叫做靜態嵌套類(Static Nested Class)。
class OuterClass { ... class InnerClass { ... } static class StaticNestedClass { ... } }
上述代碼中的InnerClass就是內部類,StaticNestedClass就是靜態嵌套類。
內部類與靜態嵌套類雖然都是嵌套類,但在使用上是有一些區別的。
內部類
比如有如下內部類的定義,
class OuterClass { ... class InnerClass { ... }}OuterClass是InnerClass的外圍類,InnerClass是OuterClass的內部類。內部類的執行個體對象都會綁定一個外圍類的執行個體對象,並且InnerClass可以訪問其所綁定的OuterClass的所有成員屬性以及方法,包括私人成員屬性以及方法。在InnerClass中通過OuterClass.this顯式的引用其所綁定的OuterClass的執行個體。要執行個體化內部類InnerClass,必須首先執行個體化其外圍類OuterClass,然後用如下的文法建立內部類的執行個體:
OuterClass outerObject = new OuterClass();OuterClass.InnerClass innerObject = outerObject.new InnerClass();
注意,上面寫得是outerObject.new InnerClass(),而不是new OuterClass.InnerClass(); 我們在執行代碼OuterClass.InnerClass innerObject = outerObject.new InnerClass()的時候,其實做了兩件事,一件事是建立一個內部類的執行個體innerObject,第二件事是讓innerObject綁定outerObject作為其外圍類的執行個體。這樣innerObject就可以訪問outerObject內的所有成員屬性以及方法了。那如果想直接跳過外圍類去初始化內部類會怎麼樣呢?代碼如下所示:
如果執行代碼InnerClass innerObject = new InnerClass(),會出現如下的編譯錯誤:No enclosing instance of type OuterClass is accessible. Must qualify the allocation with an enclosing instance of type OuterClass (e.g. x.new A() where x is an instance of OuterClass).編譯器給出的錯誤提示很明確,就是我們沒有外圍類OuterClass的執行個體就去初始化內部類了。要寫成x.new InnerClass()的形式,其中x是外圍類OuterClass的一個執行個體對象。
靜態嵌套類
有些人把靜態嵌套類成為靜態內部類,其實靜態內部類這個稱呼不嚴謹,因為內部類都是非靜態。靜態嵌套類與內部類有很大的不同,靜態嵌套類說到底就是一個靜態類,只不過是其位置位於某個類的內部罷了。假設有如下靜態嵌套類的定義:
class OuterClass { ... static class StaticNestedClass { ... }}那麼我可以像正常使用一個一般的靜態類那樣使用一個靜態嵌套類,只不過要通過其外圍類的名字來訪問靜態嵌套類的名字。所以,外圍類更像是靜態嵌套類的命名空間。比如要擷取靜態嵌套類,要使用OuterClass.StaticNestedClass。如果要建立靜態嵌套類的實力對象,使用如下的文法:
OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass();
由於靜態嵌套類的本質就是一個靜態類,所以其執行個體對象的初始化不需要也不能像內部類那樣需要綁定一個外圍類對象。由於靜態嵌套類沒有像內部類那樣綁定外部類對象,所以也就不存在靜態嵌套類不能訪問其外圍類的成員這種說法。如果我們像初始化內部類那樣初始化靜態嵌套類,也就是在建立靜態嵌套類的時候給其綁定其外圍類的執行個體對象,會怎麼樣呢?代碼如下所示:
可以發現,如果我們在初始化靜態嵌套類時強行給其綁定外圍類的執行個體對象,編譯器就會報錯:Illegal enclosing instance specification for type OuterClass.StaticNestedClass我們給靜態嵌套類OuterClass.StaticNestedClass指定了非法的外圍類的執行個體。
綜上所述,雖然內部類和靜態嵌套類都屬於嵌套類,但是二者有本質區別:內部類的執行個體化對象需要綁定一個外圍類的執行個體化對象,而靜態嵌套類的執行個體化對象不能也無法綁定外圍類的執行個體化對象。