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

Java 基礎核心:深入理解物件參考與記憶體模型

     編輯:Java 程式設計入門

我們日常編寫 Java 程式時頻繁使用「物件」概念,但物件在記憶體中究竟如何儲存?理解物件參考是掌握 Java 記憶體模型、垃圾回收機制與參數傳遞行為的關鍵基石。

什麼是物件參考?

以簡單的 Human 類別為例:

public class Human {
    private int height;
    
    public Human(int h) { this.height = h; }
    public int getHeight() { return height; }
    public void growHeight(int h) { height += h; }
}

在 main 方法中建立物件:

Human aPerson = new Human(160);

這行程式碼背後發生了三件關鍵事:

  1. new 在堆疊上配置空間:物件實際資料(欄位、方法)儲存在 JVM 堆疊記憶體中
  2. 參考變數存在堆疊:aPerson 是參考型別變數,儲存在執行緒私有的堆疊記憶體
  3. 賦值的是記憶體位址:等號右邊 new 建立物件的堆疊位址,賦值給左邊的參考變數

參考與物件的關係:風箏與人的比喻

參考指向物件

參考就像手中的風箏線,物件是天空中的風箏。程式碼中看到的是參考(風箏線),但實際操作的是物件(風箏)。所有存取物件的路徑都必須透過參考,Java 不允許直接操作記憶體位址(不像 C/C++ 的指標運算)。

參考賦值:多條線繫同一風箏

Human dummyPerson = aPerson;

多個參考指向同一物件

這行程式碼複製的是參考值(位址),而非物件本身。兩個參考指向同一個堆疊物件。透過任一參考修改物件狀態,另一個參考讀取時都會看到變化:

Human aPerson = new Human(160);
Human dummyPerson = aPerson;
System.out.println(dummyPerson.getHeight()); // 160
aPerson.growHeight(20);
System.out.println(dummyPerson.getHeight()); // 180 - 受影響!

結論:參考賦值 ≠ 物件複製。若需複製物件,須實作 clone()、建構子複製或序列化等機制。

基本型別 vs 參考型別儲存差異

型別分類儲存位置變數代表範例
基本型別堆疊數值本身int, double, boolean
參考型別參考在堆疊,物件在堆疊物件位址String, Human, int[]

基本型別宣告不需 new,JVM 直接在堆疊儲存數值;參考型別必須 new 在堆疊建立物件。

垃圾回收機制

垃圾回收示意

JVM 內建垃圾回收器(GC),核心原則:

  • 可達性分析:從 GC Roots(堆疊區參考、靜態欄位、JNI 參考等)出發,無法到達的物件視為垃圾
  • 方法結束:區域參考變數隨堆疊幀銷毀,若該物件無其他參考指向,下次 GC 即可回收
  • 記憶體洩漏風險:長生命週期物件(靜態集合、單例)持有短生命週期物件參考,導致無法回收

參數傳遞:唯有「值傳遞」

Java 方法參數傳遞永遠是值傳遞:

  • 基本型別:複製數值本身,方法內修改不影響原變數
  • 參考型別:複製參考值(位址),方法內可透過參考修改物件內容,但無法改變呼叫端的參考指向
void modify(Human h) {
    h.growHeight(10);        // 影響原物件 ✓
    h = new Human(200);      // 只改變區域參考 h,呼叫端不受影響 ✗
}

總結重點

  • new = 在堆疊建立物件,回傳位址
  • 參考在堆疊,物件在堆疊,兩者分離
  • 參考賦值複製位址,非複製物件
  • 無參考指向的物件會被 GC 回收
  • Java 只有值傳遞,參考型別傳的是「位址的值」
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved