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

深入理解 Java 陣列記憶體分配:引用變數、堆疊與垃圾回收機制

     編輯:Java 程式設計入門

前言:一個顛覆認知的現象

許多 Java 入門書都說:「基本型別存在堆疊,物件存在堆積」。但當你實際執行以下程式碼時,會發現事情沒那麼簡單:

public class Test {
    public static void main(String[] args) {
        String[] names = { "Michael", "Orson", "Andrew" }; // 靜態初始化,長度 3
        String[] animal = new String[4];                  // 動態初始化,長度 4
        names = animal;                                   // 將 names 指向 animal 所參考的陣列
        System.out.println(names.length);  // 輸出 4
        System.out.println(animal.length); // 輸出 4
    }
}

明明 names 原本長度是 3,animal 是 4,賦值後兩者長度同為 4。這是否意味著「陣列大小改變了」?答案是否定的——這揭示了引用變數與陣列物件的本質區別。

核心概念釐清

1. 引用變數 ≠ 物件本身

names 和 animal 只是引用變數(類似 C/C++ 的指標),它們儲存在堆疊中,佔據固定大小的記憶體空間(存放記憶體位址)。真正的陣列物件(包含長度、元素資料)建立在堆積上,大小一經確定不可變更。

2. 賦值操作的本質

names = animal; 只是讓 names 這個引用變數複製了 animal 手中的「地址」,兩個變數現在指向同一個堆積上的陣列物件。原本 names 指向的長度為 3 的陣列物件因無人引用,將被 GC 回收。

陣列引用指向示意圖

藍虛線:賦值前;紅線:賦值後。兩變數共同指向同一堆積物件,原物件成垃圾。

3. 基本型別也能在堆積?

陣列元素若為基本型別(如 int[]),值直接儲存在陣列物件內部(堆積上);若為參考型別(如 String[]),元素儲存的是指向堆積上 String 物件的引用。圖中 "Michael" 等字串常數同樣駐留在堆積(字串常數池)。

正確的記憶體模型描述

區域變數(含基本型別變數、引用變數)存放在堆疊;引用變數所指向的物件(陣列、類實例)存放在堆積。

Java 堆積上的物件無法直接訪問,必須透過堆疊上的引用變數作為「中介」。只有當引用變數呼叫物件方法或存取屬性時(如 dog.info()、animal[0].info()),才真正操作到堆積上的實體物件。

進階範例:物件陣列與多重引用

public class Animal {
    private String name;
    private int age;
    public Animal(String name, int age) { this.name = name; this.age = age; }
    public void info() { System.out.println(name + " " + age); }
}

public class Test {
    public static void main(String[] args) {
        Animal[] animal = new Animal[2];   // 堆積建立長度 2 的 Animal 陣列(元素初值 null)
        Animal cat = new Animal("cat", 1); // 堆積建立 cat 物件,堆疊 cat 變數存引用
        Animal dog = new Animal("dog", 2); // 堆積建立 dog 物件,堆疊 dog 變數存引用
        animal[0] = dog;  // animal[0] 與 dog 指向同一物件
        animal[1] = cat;  // animal[1] 與 cat 指向同一物件

        System.out.println(animal.length); // 2
        dog.info();        // dog 2
        animal[0].info();  // dog 2  同一物件
    }
}
物件陣列引用關係圖

藍線:賦值前;紅虛線:賦值後。animal[0]與dog、animal[1]與cat分別指向同一堆積物件。

關鍵總結

  • 陣列大小不可變:new Type[N] 在堆積建立固定大小物件。
  • 引用變數可改指向:a = b 只是讓 a 指向 b 所指的物件,不改變物件本身。
  • 堆疊存引用,堆積存實體:這是理解 Java 記憶體模型的基石。
  • 垃圾回收:當物件無任何引用指向時(如圖中原 names 陣列),GC 會自動回收。

實務啟示

理解引用機制對避免記憶體洩漏、設計高效資料結構、排查 NullPointerException 至關重要。下次看到「陣列大小變了」,請記得:是變數換了指向,不是物件變大了。

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