內部類是 Java 實現多重繼承模擬、封裝隱藏、閉包回調的核心機制。本文系統講解成員內部類、局部內部類、匿名內部類、靜態內部類(嵌套類)的語法、實例化規則、訪問權限、繼承特殊語法,並深度剖析向上轉型隱藏實現細節、多層嵌套訪問規則、內部類與閉包/回調/策略模式的關聯,配合完整可運行代碼示例,構建內部類完整知識體系。
private,向上轉型為接口返回,外部不可見具體類,實現完全信息隱藏。| 類型 | 定義位置 | 訪問外部成員 | 實例化語法 | 靜態成員 | 典型場景 |
|---|---|---|---|---|---|
| 成員內部類 | 類內部、方法外 | 任意(含 private),隱式持有 Outer.this |
Outer.Inner inner = outer.new Inner(); |
❌ 不能定義 static 成員(JDK 16+ 允許 static final) | 需持有外部狀態、多重繼承模擬 |
| 局部內部類 | 方法/代碼塊內 | 外部類成員 + final/實際最終的局部變量 | 方法內 new LocalClass() |
❌ | 方法內邏輯封裝、臨時策略實現 |
| 匿名內部類 | 表達式位置(new 後) | 同局部內部類,無名、無構造器 | new Interface() { ... } 或 new SuperClass() { ... } |
❌ | 一次性實現接口/繼承類、事件監聽、策略模式 |
| 靜態內部類 (嵌套類) | 類內部、static 修飾 | 僅外部 static 成員,無 Outer.this 引用 |
Outer.Nested nested = new Outer.Nested(); |
✅ 可定義 static 成員、嵌套 static 類 | 工具類、Builder 模式、單例持有者、不依賴外部實例 |
class A { public void f() { System.out.println("A.f()"); } }
class B {
public void f() { System.out.println("B.f()"); }
class Inner extends A { // 繼承 A
public B outer() { return B.this; } // 返回外部引用
}
public Inner inner() { return new Inner(); } // 工廠方法
}
public class MemberInnerDemo {
public static void main(String[] args) {
B b = new B();
B.Inner i1 = b.new Inner(); // 外部實例創建
B.Inner i2 = b.inner(); // 工廠方法創建
i1.f(); // A.f()
i2.outer().f(); // B.f() — 訪問外部類方法
}
}
interface Counter { int next(); }
public class LocalInnerDemo {
private int count = 0;
Counter getCounter(final String name) { // final 保證變量不變,供內部類捕獲
class LocalCounter implements Counter {
public int next() {
System.out.print(name + " "); // 訪問外部 final 變量
return count++;
}
}
return new LocalCounter();
}
public static void main(String[] args) {
LocalInnerDemo d = new LocalInnerDemo();
Counter c = d.getCounter("Local");
for (int i=0;i<4;i++) System.out.println(c.next());
}
}
public class AnonymousInnerDemo {
private int count = 0;
Counter getCounter(final String name) {
return new Counter() { // 實現接口,無名
{ // 實例初始化塊 = 匿名類的「構造器」
System.out.println("Instance initialization");
}
public int next() {
System.out.print(name + " ");
return count++;
}
};
}
public static void main(String[] args) {
AnonymousInnerDemo d = new AnonymousInnerDemo();
Counter c = d.getCounter("Anonymous");
for (int i=0;i<4;i++) System.out.println(c.next());
}
}
public class Singleton {
private Singleton() {}
private static class Holder { // 靜態內部類,類加載時初始化,線程安全、延遲加載
static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() { return Holder.INSTANCE; }
}
public class Outer {
private class Impl implements Service { // private 內部類
public void doWork() { System.out.println("Impl.doWork"); }
void internal() { System.out.println("internal detail"); }
}
public Service getService() { return new Impl(); } // 向上轉型為接口
}
// 客戶端代碼
public class Client {
public static void main(String[] args) {
Outer o = new Outer();
Service s = o.getService();
s.doWork(); // OK
// s.internal(); // 編譯錯誤:Service 無此方法
// ((Outer.Impl)s).internal(); // 編譯錯誤:Impl 是 private,不可見
}
}
Outer.this、Middle.this...
class WithInner { class Inner {} }
public class InnerSub extends WithInner.Inner {
// 必須在構造器中顯式調用 outer.super()
InnerSub(WithInner outer) { outer.super(); }
}
outer.super()。
// 經典回調:異步任務完成通知
interface Callback { void onComplete(String result); }
class Worker {
void doWork(Callback cb) {
// ... 耗時操作 ...
cb.onComplete("Done");
}
}
// 匿名內部類作為回調實現
new Worker().doWork(new Callback() {
public void onComplete(String result) {
System.out.println("Callback received: " + result);
}
});
Java 內部類看似語法糖,實則是面向對象設計模式在語言層面的原生支持:
outer.super())解決隱式外部引用初始化。掌握內部類,不僅是語法通關,更是理解Java 如何在單繼承限制下實現靈活組合、如何實現閉包語義、如何做到真正的接口隔離的關鍵。建議在項目中大膽使用匿名內部類/Lambda(JDK 8+)簡化回調代碼,靜態內部類優化單例/Builder,成員內部類建構領域模型內部協作類。