執行 new MyDate(22, 7, 1964) 時,JVM 內部完成四個關鍵步驟:
棧 (Stack) 堆
┌─────────────────┐ ┌──────────────────────┐
│ 變數: date │ ──────→ │ MyDate 物件 │
│ (參考/引用) │ │ day=22 │
└─────────────────┘ │ month=7 │
│ year=1964 │
└──────────────────────┘
public class Pet {
protected Bean be = this.b(); // 父類建構時就初始化
public Bean b() { return new Bean(); }
}
public class People extends Pet {
public void test() { be.setName("張三"); }
public void test2() { System.out.println(be.getName()); }
public static void main(String[] args) {
People pe = new People();
pe.test();
pe.test2(); // 輸出: 張三
}
}
public void test() {
Bean be = new Bean(); // 區域變數遮蔽父類欄位!
be.setName("張三");
}
public void test2() {
System.out.println(be.getName()); // 輸出: null (存取父類未初始化的 be)
}
原因:父類建構子執行時初始化 be,子類方法中宣告同名區域變數導致遮蔽,實際操作的是不同物件。
public class Singleton {
private static volatile Singleton instance;
private Singleton() {} // 私有建構子防止外部 new
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton(); // 唯一的 new
}
}
}
return instance;
}
}
StringBuilder、資料庫連線池)new 看似簡單,實則涉及類載入、記憶體分配、初始化順序、參考賦值等核心機制。理解其背後運作,能避免繼承初始化陷阱、寫出高效能程式碼、正確應用設計模式。