作為包的成員的類被稱為頂級類。一個類可以在另一個類中宣告。 這種型別的類稱為內部類。
如果在另一個類中宣告的類被顯式或隱式宣告為static
,它被稱為巢狀類,而不是內部類。
包含內部類的類稱為封閉類或外部類。
下面的程式碼宣告一個內部類。
class Outer {
public class Inner {
// Members of the Inner class go here
}
// Other members of the Outer class go here
}
Outer
類是一個頂級類。Inner
類是一個內部類。 它是外類的成員。Outer
類是Inner
類的封閉(外部)類。內部類可以是另一個內部類的封閉類。 內部類的巢狀層次沒有限制。
內部類的範例只能存在於其封閉類的範例中。
以下是內部類的一些優點:
下面的程式碼演示了存取區域性內部類中的區域性變數的規則。main()
方法宣告兩個區域性變數:x
和y
。 這兩個變數都是被宣告為 final
。變數x
在被初始化之後不能改變,變數y
也不能被改變,因為它被宣告為final
。
public class Main {
public static void main(String... args) {
final int x = 1;
final int y = 2;
class LocalInner {
void print() {
System.out.println("x = " + x);
System.out.println("y = " + y);
}
}
/*
* Uncomment the following statement will make the variable x no longer
* an effectively final variable and the LocalIneer class will not compile.
*/
// x = 100;
LocalInner li = new LocalInner();
li.print();
}
}
上面的程式碼生成以下結果。
x = 1
y = 2
內部類可以繼承另一個內部類,頂級類或其封閉類。
class A {
public class B {
}
public class C extends B {
}
public class D extends A {
}
}
class E extends A {
public class F extends B {
}
}
Java中的關鍵字static
使一個構造成為一個頂層結構。因此,不能為內部類宣告任何靜態成員(欄位,方法或初始化器)。
允許在內部類中有作為編譯時常數的靜態欄位。
class A {
public class B {
public final static int DAYS_IN_A_WEEK = 7; // OK
public final String str = new String("Hello");
}
}
每個內部類都被編譯成一個單獨的類檔案。成員內部類和靜態內部類的類檔案名格式如下:
<outer-class-name>$<member-or-static-inner-class-name>
本地內部類的類檔案名的格式如下:
<outer-class-name>$<a-number><local-inner-class-name>
匿名類的類檔案名的格式如下:
<outer-class-name>$<a-number>
類檔案名中的<a-number>
是從1
開始順序生成的數位,以避免任何名稱衝突。
可以在靜態上下文中定義一個內部類,例如靜態方法或靜態初始化器。所有靜態欄位成員都可以存取這樣的內部類。
class Outer {
static int k = 1;
int m = 2;
public static void staticMethod() {
// Class Inner is defined in a static context
class Inner {
int j = k; // OK. Referencing static field k
// int n = m; // An error. Referencing non-static field m
}
}
}