首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

深度解析 Java new 關鍵字:物件建立四大步驟與記憶體模型

     編輯:Java 相關知識

new 關鍵字核心流程

執行 new MyDate(22, 7, 1964) 時,JVM 內部完成四個關鍵步驟:

  1. 分配記憶體:在堆中為新物件分配所需記憶體空間
  2. 初始化零值:將分配的記憶體初始化為預設值 (0、null、false 等)
  3. 執行建構子:呼叫對應建構子,傳入參數初始化欄位
  4. 回傳參考:將堆中物件的參考 (引用) 賦值給棧上的變數

記憶體模型圖解

棧 (Stack)                    堆
┌─────────────────┐          ┌──────────────────────┐
│ 變數: date      │ ──────→  │ MyDate 物件          │
│ (參考/引用)     │          │ day=22               │
└─────────────────┘          │ month=7              │
                             │ year=1964            │
                             └──────────────────────┘

繼承場景下的 new 陷阱

問題程式碼

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();  // 輸出: 張三
    }
}

修改後出現 null 的版本

public void test() {
    Bean be = new Bean();  // 區域變數遮蔽父類欄位!
    be.setName("張三");
}
public void test2() {
    System.out.println(be.getName());  // 輸出: null (存取父類未初始化的 be)
}

原因:父類建構子執行時初始化 be,子類方法中宣告同名區域變數導致遮蔽,實際操作的是不同物件。

單例模式優化記憶體與 new 使用

懶漢式單例 (線程安全版)

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;
    }
}

new 關鍵字效能考量

  • 逃逸分析:JIT 編譯器若發現物件未逃逸出方法,可能優化為棧上分配 (標量替換)
  • TLAB:Thread-Local Allocation Buffer 讓多線程分配無鎖競爭
  • 物件復用:高頻建立的小物件可考慮物件池模式 (如 StringBuilder、資料庫連線池)

總結

new 看似簡單,實則涉及類載入、記憶體分配、初始化順序、參考賦值等核心機制。理解其背後運作,能避免繼承初始化陷阱、寫出高效能程式碼、正確應用設計模式。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved