Java 陣列是 call by address?Python 是 call by reference?兩個常見誤解一次釐清
· 閱讀時間約 6 分鐘
Java 陣列是 call by address?Python 是 call by reference?兩個常見誤解一次釐清

剛開始教初學者時,我很常看到同一種答案反覆出現:
- Java 陣列傳進方法後可以改到內容,所以它是 call by address
- Python 的 list 傳進函式後也能改到外面的值,所以它是 call by reference
這兩句話都很像對的,因為從執行結果看起來,真的很像「我把東西交進去,裡面改了,外面也跟著變」。但也正因為「看起來很像」,但又似乎看過相異的解釋,深怕錯誤的解釋會影響學習效果。
這篇我從錯誤認知出發,借助 AI 詢問釐清自己的觀念,最後希望能回到官方真正的說法。
上述兩個說法都不夠精確

Java
不是 call by address,而是 pass by value。只是當你傳的是物件或陣列時,傳進去的那個「值」,是參考值的副本。
Python
Python 官方也不把它叫做 call by reference。Python FAQ 的說法是 arguments are passed by assignment,而且明白寫到 there's no ... call-by-reference。
所以,如果要用一句最不容易誤導學生的話來說:
Java 一律是傳值;Python 不是 call by reference。
為什麼這麼多人會學成錯的?

因為下面這種程式,真的很容易讓人誤會。
Java 範例
public class Main {
public static void change(int[] arr) {
arr[0] = 100;
}
public static void main(String[] args) {
int[] nums = {1, 2, 3};
change(nums);
System.out.println(nums[0]);
}
}
輸出:
100
Python 範例
def change(arr):
arr[0] = 100
nums = [1, 2, 3]
change(nums)
print(nums[0])
輸出:
100
學生看到這裡,第一個反應通常都很合理:
「都改得到外面,那不就是 reference 嗎?」
這個推論很自然,但問題就出在這裡:「改得到同一個物件內容」不等於「呼叫端變數本身是被 reference 傳進去」。
