內部類是 Java 語言中一項強大且靈活的特性,它允許將一個類的定義置於另一個類的內部。這不僅能實現邏輯上的封裝分組,更能優雅地解決「多重實現」與「回調」等棘手問題。本文系統整理內部類的分類、語法細節、進階用法及核心設計動機,並附帶完整代碼示例,幫助開發者徹底掌握這項技術。
根據定義位置與 static 修飾符,內部類主要分為四類:
static 修飾,持有外部類引用。static 修飾,不依賴外部類實例,行為類似頂級類。成員內部類實例綁定於外部類實例,可無條件訪問外部類所有成員(含 private)。創建語法:
OuterClass outer = new OuterClass(); OuterClass.InnerClass inner = outer.new InnerClass();
若需在內部類中獲取外部類引用,使用 OuterClass.this。注意:成員內部類不能定義 static 字段或方法(編譯期常量除外),因為它依賴外部實例存在。
public class DoThis {
void f() { System.out.println("DoThis.f()"); }
public class Inner {
public DoThis getOuter() { return DoThis.this; }
}
public Inner getInner() { return new Inner(); }
public static void main(String[] args) {
DoThis d = new DoThis();
DoThis.Inner inner = d.getInner();
inner.getOuter().f(); // 輸出: DoThis.f()
}
}
加上 static 後,嵌套類不再持有外部類引用,可直接實例化:
OuterClass.NestedClass nested = new OuterClass.NestedClass();
它無法直接訪問外部類的非靜態成員,常用於將相關工具類組織在一起,或作為接口的默認實現載體。
public interface ClassInInterface {
void howdy();
class Test implements ClassInInterface {
@Override public void howdy() { System.out.println("Howdy"); }
public static void main(String[] args) { new Test().howdy(); }
}
}
定義在方法中,僅在該方法執行期間可用,可訪問方法的 final 或實際上最終的局部變量。
public class Parcel5 {
public Destination destination(String s) {
class PDestination implements Destination { ... }
return new PDestination(s);
}
}
定義在 if、for 等塊中,作用域更窄,編譯器將其視為局部類。
new Interface() { ... }new SuperClass(args) { ... }new Type() {{ field = value; }}{ ... } 初始化。final 或 effectively final。內部類可多層嵌套,內層類透明訪問所有外層類成員:
class A { private void f() {} class B { private void g() {} public class C { void h() { g(); f(); } } } }
interface Incrementable { void increment(); }
class Callee2 extends MyIncrement {
private int i = 0;
public void increment() { super.increment(); i++; System.out.println(i); }
private class Closure implements Incrementable {
public void increment() { Callee2.this.increment(); }
}
Incrementable getCallbackReference() { return new Closure(); }
}
class Caller {
private Incrementable callback;
Caller(Incrementable cbh) { callback = cbh; }
void go() { callback.increment(); }
}
// 使用:new Caller(c2.getCallbackReference()).go();
class ChildInner extends Outer.Inner { ChildInner(Outer outer) { outer.super(); } }內部類不僅是語法糖,更是 Java 實現「對象級閉包」、「多重實現解耦」與「框架級回調」的基石。掌握其生命周期、作用域規則與訪問權限,能讓代碼更內聚、更具擴展性。實際開發中,優先考慮 static 嵌套類以降低耦合;需訪問外部狀態時再用非靜態內部類;匿名類適合一次性邏輯;局部類用於複雜方法內部封裝。