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

Java 數組內存分配深度解析:引用變量與堆對象的真實關係

     編輯:Java 相關知識

前言:顛覆認知的「數組大小不可變」

很多書上說「基本類型存棧,對象存堆」,這其實是片面的。通過一個簡單的例子,我們將揭開 Java 數組內存分配的真相。

現象:數組大小似乎變了?

public class Test {
    public static void main(String[] argv) {
        String[] names = { "Michael", "Orson", "Andrew" }; // 長度 3
        String[] animal = new String[4]; // 長度 4
        names = animal; // 賦值
        System.out.println(names.length);  // 輸出 4
        System.out.println(animal.length); // 輸出 4
    }
}

「Java 數組大小不可變」是指數組對象本身在堆中創建後大小固定。但 names 和 animal 只是引用變量(類似 C 指針),它們存儲在棧中,可以指向不同的堆對象。賦值 names = animal 只是讓 names 指向 animal 所指的那個長度為 4 的數組對象,原長度 3 的數組對象因無引用將被 GC 回收。

圖解內存結構

數組引用變量指向堆對象示意圖

  • 藍虛線: 賦值前,names 指向長度 3 的數組,animal 指向長度 4 的數組。
  • 紅實線: 賦值後,兩個引用變量同時指向同一個長度 4 的數組對象。

基本類型也存堆?

例中的 "Michael" 等字符串是基本類型嗎?它們是對象,存儲在堆中(或常量池)。正確的表述是:

局部變量(引用類型變量、基本類型變量)放在棧內存中;但變量所引用的對象(包括數組、自定義類對象、String 等)保存在堆內存中。

Java 堆中的對象不能直接訪問,必須通過棧中的引用變量作為中介。

什麼時候引用變量「變成」真正的對象?

只有當棧內存中的引用變量調用了對象的方法或訪問了對象的屬性時,它才真正表現為對象操作。

代碼驗證

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[] argv) {
        Animal[] animal = new Animal[2];
        Animal cat = new Animal("cat", 1);
        Animal dog = new Animal("dog", 2);
        animal[0] = dog;
        animal[1] = cat;
        // 此時 cat、dog、animal[0]、animal[1] 都是引用變量,指向堆中對象
        dog.info();        // 調用方法,輸出 "cat 1"
        animal[0].info();  // 同一對象,輸出 "cat 1"
    }
}

圖解對象引用關係

對象引用賦值前後示意圖

  • 藍線: 賦值前,cat、dog、animal[0]、animal[1] 分別指向不同對象(或 null)。
  • 紅虛線: 賦值後,animal[0] 與 dog 指向同一對象,animal[1] 與 cat 指向同一對象。

總結

  1. 數組大小不可變針對的是堆中的數組對象,而非棧中的引用變量。
  2. 引用變量存棧,對象存堆是核心內存模型。
  3. 賦值只是改變引用指向,不會複製對象,也不會改變對象大小。
  4. 基本類型變量直接存值於棧,但包裝類、String、數組等引用類型變量存的是堆地址。

理解這一點,是掌握 Java 內存管理、避免淺拷貝陷阱、優化性能的基石。

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