巢狀類(Nested Classes)
Java語言允許你在一個類中再定義類,這樣的類,我們稱之為巢狀類。格式如下:
class OuterClass{
...
class NestedClass{
...
}
}
術語:巢狀類分為兩種,一種是靜態;一種是非靜態。宣告為靜態的稱之為靜態巢狀類;非靜態的稱之為內部類。
class OuterClass{
...
static class StaticNestedClass{
...
}
class InnerClass{
...
}
}
NestedClass是其OuterClass的成員。對於內部類,可以訪問OuterClass的其他成員,儘管成員被定義為private,同樣允許訪問。然而,靜態巢狀類卻不能訪問。作為OuterClass的一個成員,巢狀類可以定義為private,public,protected。
為什麼使用巢狀類?
1、某個類只在單一地方使用,使用巢狀類方便管理;
2、提高了封裝性;
3、可讀性和可維護性更好。
靜態巢狀類
正如類中的方法和變數,靜態巢狀類與OuterClass也是有聯絡。如同類中的靜態方法,靜態巢狀類不能直接訪問OuterClass的例項變數和方法:僅僅可以通過對像的引用來訪問它們。
注意:靜態巢狀類與OuterClass(以及其他類)的例項成員互動就像跟任何其他頂級類一樣。實際上,靜態巢狀類就是為了打包方便巢狀在其他頂級類中。
靜態巢狀類是通過使用OuterClass類名來訪問的:
OuterClass.StaticNestedClass
例如,為靜態巢狀類建立一個物件的語法:
OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass();
內部類
正如類中的例項方法和變數,內部類與OuterClass的例項有聯系,並且可以直接訪問物件方法和變數。因為內部類與例項有聯絡,所以它不能定義任何靜態成員。
內部類的物件存在於OuterClass的例項物件當中。內部類例項僅僅只能存在一個OuterClass例項當中並且可以直接訪問OuterClass例項的方法和屬性。
為了例項化一個內部類,你必須首先例項化OuterClass。然後建立一個內部類物件,語法:OuterClass.InnerClass innerObject = outerObject.new InnerClass();
還有兩種特殊的內部類:區域性類和匿名類。
訪問內部類成員變數的經典例項:
public class ShadowTest {
public int x = 0;
class FirstLevel {
public int x = 1;
void methodInFirstLevel(int x) {
System.out.println("x = " + x);
System.out.println("this.x = " + this.x);
System.out.println("ShadowTest.this.x = " + ShadowTest.this.x);
}
}
public static void main(String... args) {
ShadowTest st = new ShadowTest();
ShadowTest.FirstLevel fl = st.new FirstLevel();
fl.methodInFirstLevel(23);
}
}
輸出結果:
x = 23
this.x = 1
ShadowTest.this.x = 0
內部類的序列化
對於內部類(包括區域性類和匿名類)的序列化,Java編譯器編譯內部類的構造方法時,會建立一個合成的建構函式(synthetic constructs),對於JVM來說,它沒有什麼不同,但是,不同的Java編譯器編譯出來的.class檔案可能會不同,因此,當你對內部類使用不同的JRE進行序列化和解序列化時可能會面臨相容性的問題。