四大類型對比
| 類型 | 定義位置 | 存取外部成員 | 實例化方式 | 典型用途 |
| 成員內部類 | 類內部、方法外 | 直接存取(含 private) | outer.new Inner() | 邏輯強相關、需頻繁存取外部狀態 |
| 區域內部類 | 方法/程式碼塊內 | 僅 final/效能 final 區域變數 | 方法內直接 new | 一次性邏輯封裝、策略模式實作 |
| 匿名內部類 | 表達式中 | 同區域內部類 | new Interface/Parent() { ... } | 單次實作介面/抽象類、事件監聽器 |
| 靜態內部類 | 類內部、static 修飾 | 僅 static 成員 | new Outer.StaticInner() | 工具類、Builder、單例持有者、避免外部引用洩漏 |
程式碼範例精華
class Outer {
private int outerField = 10;
static String staticField = "static";
// 1. 成員內部類
class MemberInner {
void print() { System.out.println(outerField); }
}
// 2. 靜態內部類
static class StaticInner {
void print() { System.out.println(staticField); }
}
void method() {
final int localVar = 20;
// 3. 區域內部類
class LocalInner {
void print() { System.out.println(localVar); }
}
new LocalInner().print();
// 4. 匿名內部類
Runnable r = new Runnable() {
@Override public void run() { System.out.println(outerField); }
};
new Thread(r).start();
}
}
// 實例化
Outer outer = new Outer();
Outer.MemberInner mi = outer.new MemberInner();
Outer.StaticInner si = new Outer.StaticInner();
關鍵注意事項
- 成員/區域/匿名內部類隱含持有外部實例引用,可能導致記憶體洩漏(如長壽命外部類實例持有大量內部類)
- 靜態內部類無外部引用,適合單例模式
- 區域內部類存取區域變數需
final 或「效能 final」(JDK 8+ 不需寫 final)
- 匿名類無法定義建構子,可用實例初始化塊
{ } 替代
設計選擇指南
- 需存取外部實例狀態 → 成員內部類
- 僅方法內使用、邏輯簡單 → 區域/匿名內部類
- 無需外部實例、獨立功能 → 靜態內部類(首選)
- Java 8+ 優先用 Lambda 替代單一方法介面的匿名類