Java 程式執行時,資料主要存放在兩個記憶體區域:棧與堆。與 C++ 不同,Java 自動管理這兩區記憶體,開發者無法直接操作。理解其差異與運作機制,對寫出高效能、無 Bug 的程式碼至關重要。
| 特性 | 棧 | 堆 |
|---|---|---|
| 存取速度 | 極快,僅次於 CPU 登錄器 | 較慢,需動態分配 |
| 資料大小/生命週期 | 必須確定,缺乏彈性 | 可動態分配,生命週期不固定 |
| 管理方式 | 自動釋放(區塊結束即釋放) | 由垃圾收集器 (GC) 自動回收 |
| 資料共享 | 支援基本型別字面值共享 | 物件預設不共享 |
共 8 種:int, short, long, byte, float, double, boolean, char(注意:無 String 基本型別)。
定義方式如 int a = 3;,稱為自動變數。其特點:
int a = 3; int b = 3; 時,a、b 指向同一個字面值 3 的位址修改 a = 4 時,JVM 會在棧尋找或建立字面值 4 的位址,讓 a 指向新位址,b 不受影響。
如 Integer, String, Double 等。使用 new() 動態建立,靈活但存取較慢。
String 同時支援兩種建立方式:
String str1 = new String("abc"); // 堆中建立新物件
String str2 = "abc"; // 棧中字面值池,可能共享
strstr 指向物件 oString s1 = "abc";
String s2 = "abc";
System.out.println(s1 == s2); // true,同一物件
s1 = "bcd";
System.out.println(s1 == s2); // false,s1 指向新物件
String s3 = s1;
String s4 = "bcd";
System.out.println(s1 == s4); // true,s4 共享 s1 指向的物件
String s1 = new String("abc");
String s2 = "abc";
System.out.println(s1 == s2); // false,兩個不同物件
結論: 凡用 new() 建立,必在堆中新建物件,不與棧共享。
所有包裝類別(含 String)皆為 immutable。修改值實則是建立新物件,原參考指向新物件。
String str = "abc":JVM 自動決定是否重用物件,效能較佳(享元模式思想)。equals(),比較參考用 ==。StringBuffer/StringBuilder 避免大量物件建立開銷。String str = "abc" 建立的是參考變數,不一定建立新物件。掌握棧堆差異與 String 內部機制,能有效避免記憶體洩漏、效能瓶頸與難以發現的邏輯錯誤。