Java 允許在類內部定義另一個類,稱為嵌套類。根據是否有 static 修飾符,分為 內部類 (非 static) 和 嵌套靜態類 (static)。嵌套類增強了封裝性、邏輯分組和代碼組織能力。
class Outer {
private String outerField = "外部字段";
class Inner { // 非 static,內部類
void accessOuter() {
System.out.println(outerField); // 直接訪問外部私有字段
System.out.println(Outer.this.outerField); // 顯式引用外部實例
}
}
}
public class Test {
public static void main(String[] args) {
Outer outer = new Outer();
// 必須先有外部實例,再創建內部實例
Outer.Inner inner = outer.new Inner();
inner.accessOuter();
}
}
關鍵語法:outer.new Inner() — 內部類實例隱含持有外部實例引用 (Outer.this)。
private:僅外部類內部可訪問default:同包可訪問protected:子類可訪問public:任意處可訪問
class Human {
private String name;
class Cup {
String whosCup() { return name; } // 捕獲外部實例的 name
}
Human(String n) { name = n; }
}
public class Test {
public static void main(String[] args) {
Human me = new Human("Vamei");
Human him = new Human("Jerry");
Human.Cup myCup = me.new Cup();
Human.Cup hisCup = him.new Cup();
System.out.println(myCup.whosCup()); // Vamei
System.out.println(hisCup.whosCup()); // Jerry
}
}
閉包本質:內部類實例攜帶創建時的外部實例引用,能訪問該實例的所有成員 (含 private),實現了「狀態捕獲」。
Runnable r = new Runnable() {
@Override public void run() { System.out.println("匿名內部類"); }
};
常用於事件監聽、線程創建、回調等場景,是無名內部類的簡寫形式。
class Outer {
static class Nested { // static 修飾
void staticMethod() {
// 無法直接訪問外部實例字段
// System.out.println(outerField); // 編譯錯誤
}
}
}
Outer.Nested nested = new Outer.Nested(); // 直接創建
嵌套靜態類不持有外部實例引用,本質是頂層類,只是命名空間嵌套在外部類中。
class Human {
static class Mongolian { void shout() { System.out.println("Oh...Ho..."); } }
}
Human.Mongolian m = new Human.Mongolian();
m.shout();
| 特性 | 內部類 | 嵌套靜態類 |
|---|---|---|
| 關鍵字 | 無 static | static |
| 持有外部引用 | 是 | 否 |
| 創建語法 | outer.new Inner() | new Outer.Nested() |
| 訪問外部實例成員 | 直接訪問 | 不可直接訪問 |
| 訪問外部靜態成員 | 可 | 可 |
| 可定義靜態成員 | 否 (JDK 16+ 允許) | 是 |
| 序列化風險 | 高 (隱含外部引用) | 低 |
| 典型用途 | 閉包、迭代器、事件監聽 | 工具類、構建器、命名空間 |
class Outer {
void method() {
final int localVar = 10; // JDK 8+ 隱式 final
class LocalInner {
void print() { System.out.println(localVar); }
}
new LocalInner().print();
}
}
定義在方法內部,只能訪問 final/隱式 final 的局部變量,作用域限於方法內。
Map.Entry、LinkedList.NodeStringBuilder、HttpRequest.Builder嵌套類是 Java 面向對象建模的重要工具。內部類提供閉包能力,捕獲外部實例狀態;靜態嵌套類提供命名空間組織,無外部引用開銷。正確選擇二者,能編寫出更封裝、更安全、更具表達力的代碼。JDK 8+ Lambda 表達式在大多數單方法接口場景下替代了匿名內部類,但內部類的閉包語義在複雜狀態捕獲場景仍不可替代。