在 Bag 類別中將節點類別 Node 宣告為 private static class Node,核心目的有二:不持有外部類實例引用(節省記憶體、允許獨立實例化)、實現線程安全的延遲初始化單例(Holder 模式)。
| 特性 | 非 static 內部類 | static 內部類 |
|---|---|---|
| 持有外部實例引用 | 是 (Outer.this) | 否 |
| 實例化需外部實例 | 是 (outer.new Inner()) | 否 (new Outer.Inner()) |
| 可存取外部私有成員 | 是 (含實例欄位/方法) | 僅 static 成員 |
| 序列化包含外部引用 | 是 | 否 |
Bag 實例可能建立成千上萬個 Node,若非 static,每個 Node 都隱含一個指向 Bag 的引用(8 bytes),造成額外記憶體佔用與 GC 壓力。Node 純粹是資料載體 (item, next),不需存取 Bag 的任何實例狀態,語義上屬於「靜態巢狀類別」。Bag 未直接用單例,但此模式是實現 Initialization-on-demand holder idiom 的標準載體:public class Singleton {
private Singleton() {}
private static class Holder {
static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() { return Holder.INSTANCE; }
}
類別載入機制保證線程安全、延遲初始化、無同步開銷。Iterator 需存取集合內部狀態)。預設內部類聲明為 static,除非確有需要存取外部實例成員。這能避免記憶體洩漏(如非 static 內部類實例被長期持有導致外部類無法 GC),也是 Effective Java 條目 24 建議。
理解 static 內部類的「無外部引用」特性,是寫出高效、無洩漏 Java 代碼的關鍵。