首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

Java 對象創建與引用變量聲明的區別:new、聲明、初始化的內存模型圖解

     編輯:程式設計疑難解答

核心概念辨析

術語代碼形式動作內存影響
聲明引用變量Y b;在棧幀分配引用變量槽位(4/8 字節),初始值為 null無堆對象創建
創建對象new Y()在堆分配對象內存,調用構造函數初始化,返回引用地址堆分配對象,返回地址
賦值/初始化b = new Y()將創建對象返回的地址存入引用變量 b引用變量指向堆對象
合寫Y b = new Y();聲明 + 創建 + 賦值,一條語句完成等價於分開寫

內存圖解

棧                                 堆
┌──────────────┐                   ┌────────────────────┐
│ main() 幀    │                   │ Y 實例             │
│ Y b ─────────┼──────────────────►│ 字段...            │
│ (引用變量)   │    地址 0x7f...   │ 方法表指針         │
└──────────────┘                   └────────────────────┘

類成員變量初始化的編譯器行為

class X {
    T b = new Y();  // 成員變量聲明處初始化
    X() {
        System.out.print("X");
    }
}

編譯器會將成員初始化代碼**自動搬移到構造函數開頭**,等價於:

class X {
    T b;
    X() {
        b = new Y();  // 編譯器插入這裡,super() 之後、構造函數體之前
        System.out.print("X");
    }
}
  • 順序:父類靜態初始化 → 子類靜態初始化 → 父類成員初始化/構造塊 → 父類構造函數 → 子類成員初始化/構造塊 → 子類構造函數。
  • 成員初始化在構造函數體**之前**執行,可被構造函數覆蓋。

經典面試題陷阱

Y b;           // ① 聲明引用,b = null
b = new Y();   // ② 創建對象,賦值給 b
Y c = b;       // ③ 複製引用,c 指向同一對象
c = new Y();   // ④ 創建新對象,c 指向新對象,b 不變

問題:執行 ④ 後,堆上有幾個 Y 對象?
答案:**兩個**。`b` 和 `c` 分別指向不同對象,第一個對象若無其他引用,將被 GC 回收。

靜態變量與實例變量的區別

構造函數 vs 靜態構造塊

class Student {
    static { System.out.print("靜態塊 "); }  // 類加載時執行一次
    { System.out.print("實例塊 "); }         // 每次 new 前執行
    public Student() { System.out.print("構造 "); }
}
  • `new Student()` 輸出:`靜態塊 實例塊 構造`(首次)
  • 再次 `new Student()` 輸出:`實例塊 構造`(靜態塊不再執行)

總結

  • 聲明 ≠ 創建:`Y b;` 只在棧上放一個「遙控器」,按鈕還沒按(`null`)。
  • `new` 才是創建:在堆上造「電視機」,返回遙控器頻道(地址)。
  • 合寫 `Y b = new Y();` 是語法糖,編譯器拆解為聲明 + new + 賦值。
  • 成員初始化 本質是編譯器幫你在構造函數開頭插入賦值代碼。
  • 引用複製 只複製遙控器,不複製電視機;`==` 比較遙控器頻道,`equals()` 比較電視機內容(需重寫)。

理解「棧上引用、堆上對象、地址連接」的三角關係,是掌握 Java 內存模型、避免空指針、解決 GC 問題的基石。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
特性實例變量靜態變量
歸屬屬於對象實例屬於類
創建時機每次 `new` 時類加載時(首次主動使用)
內存區域堆方法區/元空間
訪問方式`obj.field``Class.field` 或 `obj.field`(不推薦)
生命週期隨對象 GC 結束隨類卸載結束(通常伴隨 JVM)