內部類:定義在另一個類內部的類。
外部類:包含內部類定義的類。
頂層類:非嵌套定義的普通類。
public class Outer {
public static class Inner1 { ... } // public
static class Inner2 { ... } // package-private
private static class Inner3 { // private
public static class Inner4 { } // 嵌套靜態類
}
}
特性:
Outer.thisstatic 成員Outer.Inner1JDK 實戰:LinkedList.Entry、HashMap.Node — 節點類僅服務於外部容器,無需外部實例上下文。
public class Outer {
private int data;
public class Inner1 {
private int data; // 隱藏外部同名字段
public Inner1() {
data = 1; // 訪問自身字段
Outer.this.data = 1; // 訪問外部字段
}
}
private class Inner3 {
public class Inner4 { } // 成員類可嵌套成員類
}
// 接口隱式 static
interface Inner5 { } // 實為靜態成員類
}
特性:
Outer.this 引用static 成員(static final 除外)interfaceOuter.Inner1 inner = outer.new Inner1();JDK 實戰:AbstractList.Itr — 迭代器需訪問列表內部字段(size, modCount, elementData),無需額外暴露接口。
public class Outer {
private int instanceField;
private static int staticField;
{ // 實例初始化塊
int local1 = 0;
final int local2 = 1;
class Inner1 {
public Inner1() {
instanceField = 1; // 訪問外部實例字段
// System.out.print(local1); // 編譯錯誤:非 final
System.out.print(local2); // 允許:final 或 effectively final
}
}
// 無訪問修飾符
}
static { // 靜態初始化塊
class Inner2 { // 局部靜態類
public Inner2() { staticField = 1; }
}
}
public void method() {
class Inner3 { } // 方法局部類,僅在方法內可見
}
}
核心約束:只能訪問 final/effectively final 局部變量(生命週期安全);無訪問修飾符;不能定義接口。
public class Outer {
public void demo() {
// 實現接口
Action action = new Action() {
public void doAction() { System.out.println("Anonymous"); }
};
action.doAction();
// 繼承類
new BaseClass(5) {
public void printData() { System.out.println("data = " + getData()); }
}.printData();
}
}
interface Action { void doAction(); }
class BaseClass {
private int data;
public BaseClass(int data) { this.data = data; }
public int getData() { return data; }
}
本質:無構造器(使用實例初始化塊)、隱式繼承/實現、僅用於一次性行為定義。
非靜態內部類實例持有外部引用。若內部類實例生命週期長於外部類(如靜態集合緩存、單例持有),將阻礙外部實例 GC。解決:改為靜態內部類 + 弱引用,或傳遞所需數據而非整個外部實例。