HOWTO · Java
在 Java 中陣列是以值傳遞還是以引用傳遞
本文介紹了 Java 中檢查陣列是按值傳遞還是按引用傳遞。
本頁內容
Java 會以值傳遞每個方法引數。當引數是陣列時,複製到參數中的值是陣列物件的參考。因此,呼叫端的變數和方法參數可能指向同一個物件,但兩者仍是不同的變數。這就是為什麼變更陣列元素會讓呼叫端看見變化,而將另一個陣列指定給參數則不會。
Java 如何傳遞引數
參考是一種能讓程式存取物件的值;參考本身並不是物件。方法收到的是該參考值的副本。呼叫開始時,呼叫端的陣列變數和方法參數都指向同一個陣列物件。Java 不會以參考方式傳遞陣列變數本身,因此方法無法透過指定自己的參數來替換呼叫端的變數。
重點在於區分變更物件與變更變數。指定陣列元素會變更共用物件;指定方法參數則只會變更參數所持有的參考副本。即使這兩種操作都發生在被呼叫的方法中,結果仍然不同。
陣列元素變更如何影響呼叫端
方法寫入 values[index] 時,會變更兩個參考都能存取的陣列物件中的元素。方法返回後,呼叫端會看到該元素的變化。傳遞的仍是參考值的副本;元素變更之所以可見,是因為這個副本仍指向同一個物件。
方法重新指定陣列參數時會發生什麼事
將新陣列指定給方法參數後,該參數便會指向另一個物件。這不會改變呼叫端的變數;該變數仍指向原本的陣列。呼叫端可以看見重新指定之前對原始物件所做的變更,但不會取得參數的新參考。若要替換呼叫端的陣列變數,可以讓方法傳回新陣列,並在呼叫處指定傳回值;也可以直接變更原始陣列。
primitive 參數的行為
primitive 引數同樣以值傳遞:參數一開始取得的是 primitive 值的副本。如果方法將不同的數值指定給該參數,呼叫端的變數不會改變。這和重新指定陣列參數類似,與變更陣列元素不同。陣列的情況多了一個參考:這個參考值的副本可以用來變更共用物件,而指定新的參考只會影響區域參數。
執行以下自足範例:
本節中的程式碼以及顯示的標籤或輸出仍為英文。
public class ArrayArgumentDemo {
static void changeFirst(int[] values) {
values[0] = 9;
}
static void replaceParameter(int[] values) {
values = new int[] {7, 8};
}
static void changeNumber(int number) {
number = 9;
}
public static void main(String[] args) {
int[] numbers = {1, 2};
changeFirst(numbers);
System.out.println(numbers[0]);
replaceParameter(numbers);
System.out.println(numbers[0]);
int count = 1;
changeNumber(count);
System.out.println(count);
}
}
9
9
1
第一個輸出顯示變更後的元素。第二個輸出顯示,方法參數被指定為另一個陣列後,呼叫端的陣列仍維持原狀。最後一個輸出則顯示,呼叫端的 primitive 變數也沒有改變。
重點整理
Java 一律以值傳遞引數,包括陣列參考。當呼叫端和方法參數指向同一個陣列物件時,元素變更會反映在呼叫端。重新指定參數只會改變它的區域參考;指定新值給 primitive 參數也只會改變它的區域副本。區分物件變更與參數指定,就能預測這些行為。