代碼現象
public class Main {
String str = new String("good");
char[] ch = {'a','b','c'};
public void change(String str, char[] ch) {
str = "test ok"; // 重新指向新對象
ch[0] = 'g'; // 修改陣列內容
}
public static void main(String[] args) {
Main m = new Main();
m.change(m.str, m.ch);
System.out.print(m.str + " and "); // 輸出 good
System.out.print(m.ch); // 輸出 gbc
}
}
核心解釋
Java 唯一支援「值傳遞」
- 基本類型:傳遞值的副本,方法內修改不影響原變數。
- 引用類型:傳遞引用的副本(即記憶體地址),方法內可通過引用修改對象內部狀態,但無法改變外部引用指向的對象。
具體分析
str = "test ok":方法參數 str 指向新字符串對象,外部 m.str 仍指向原 "good" 對象 → 不變。
ch[0] = 'g':方法參數 ch 與外部 m.ch 指向同一個陣列對象,修改陣列元素 → 生效。
記憶體圖示
棧帧 main: m.str ──────► 堆 "good"
m.ch ──────► 堆 ['a','b','c']
棧帧 change: str ──────► 堆 "test ok" (新對象)
ch ──────► 堆 ['a','b','c'] (同一陣列)
延伸:如何在方法中修改外部引用?
- 返回新對象:
str = change(str)。
- 使用容器/包裝類:
AtomicReference、StringBuilder、自定義 Holder 類。