匿名內部類是「繼承某類」或「實現某介面」的無名子類,並在同一行完成定義與實例化。本質上是一個「帶實現內容的對象」。
new 父類或介面() {
// 子類/實現類的類體:欄位、方法、初始化塊
};
abstract class AbsDemo { abstract void show(); }
class Outer {
int x = 3;
public void function() {
AbsDemo d = new AbsDemo() { // 匿名子類實例
int num = 9; // 可定義欄位
void show() { // 必須實現抽象方法
System.out.println("num===" + num);
}
void abc() { // 可新增方法
System.out.println("haha");
}
};
d.show(); // 編譯通過
// d.abc(); // 編譯錯誤:引用型別為 AbsDemo,無 abc()
}
}
public class Demo {
public static void main(String[] args) { new Outer().function(); }
}
final 或 effectively final (Java 8+) 的區域變數。Outer.this,可能導致記憶體洩漏。Outer$1.class、Outer$2.class 等合成類。| 場景 | 範例 | 建議 |
|---|---|---|
| 事件監聽器 | button.addActionListener(e -> ...) | Java 8+ 優先用 Lambda |
| 執行緒/任務 | new Thread(() -> { ... }).start() | 同左,或實現 Runnable/Callable |
| 臨時策略實現 | Collections.sort(list, new Comparator() {...}) | Lambda 或方法引用 |
| 測試桩/模擬對象 | new HttpClient() { ... } | 簡單場景可用,複雜改用 Mockito |
匿名內部類是 Java 早期實現「函數式風格」的語法糖,Java 8 Lambda 大幅取代其地位。理解其編譯原理、捕獲規則與多態限制,有助於維護舊代碼、排查類加載/序列化問題,並在無法用 Lambda 時(如實現多方法介面、需定義欄位/構造器)正確使用。