匿名內部類編譯後會產生獨立 OuterClass$1.class、OuterClass$2.class...,本質等同於寫一個實作類再實例化,只是簡化了「定義類 → 實例化」兩步為一步。
public interface IWriter { void write(); }
IWriter writer = new IWriter() {
@Override public void write() { System.out.println("IWriter write..."); }
};
writer.write();
public abstract class AbstractWriter { public abstract void write(); }
AbstractWriter aw = new AbstractWriter() {
@Override public void write() { System.out.println("AbstractWriter write..."); }
};
aw.write();
public class TextWriter implements IWriter {
@Override public void write() { System.out.print("text writer.."); }
}
TextWriter tw = new TextWriter() {
@Override public void write() { System.out.println("TextWriter 2 write..."); }
};
tw.write();
Thread t = new Thread() {
@Override public void run() {
new IWriter() {
@Override public void write() { System.out.println("Thread write..."); }
}.write();
}
};
t.start(); // 注意:此處應用 start() 而非 run()
{ ... }。Java 8+ 若介面為函數式介面(單一抽象方法),優先使用 Lambda:
// 匿名內部類
Runnable r1 = new Runnable() { @Override public void run() { System.out.println("Hi"); } };
// Lambda
Runnable r2 = () -> System.out.println("Hi");
但抽象類、多方法介面、需存取 this 參考外部類成員時,匿名內部類仍不可替代。
匿名內部類是「就地實作、一次性使用」的利器,核心場景:事件監聽器、執行緒任務、策略模式臨時實作、測試 Mock。理解其編譯產物與捕獲變數機制,能避免記憶體洩漏與行為錯誤。Lambda 簡化了函數式介面情境,但未完全取代匿名內部類的所有用途。