程式碼範例
public static void changeStr(String str) {
str = "welcome"; // 嘗試修改參考指向
}
public static void main(String[] args) {
String str = "1234";
changeStr(str);
System.out.println(str); // 輸出 "1234"
}
記憶體圖解
| 區域 | 儲存內容 | 本例對應 |
| 棧 | 基本型別變數、物件參考(引用) | main 中的 str 參考變數;changeStr 中的參數 str(副本) |
| 堆 | 物件實體(new 出來的實例、字串常數池物件) | "1234" 字串物件;"welcome" 字串物件 |
執行流程
main:在常數池找/建立 "1234",str 參考指向它。
- 呼叫
changeStr(str):**參考傳值**,將參考值複製給形參 str(棧上新槽位)。
- 方法內
str = "welcome":形參改指向常數池的 "welcome",**不影響** main 的參考。
- 方法結束,形參銷毀;main 的
str 仍指向 "1234"。
關鍵結論
- Java **只有傳值呼叫**(Call by Value)。物件傳遞的是「參考的值」。
- 方法內重新指派參數(
= new ... 或 = "literal")不影響呼叫端變數。
- 若在方法內呼叫物件的**修改方法**(如
list.add()、obj.setName()),則會改變堆上共享物件的狀態,呼叫端可見。
String 為不可變類別,任何「修改」實際都是建立新物件、改變參考指向。
圖示
main stack: str ──────► Heap: "1234" (常數池)
changeStr stack: str (copy) ──► Heap: "welcome" (常數池)