首先給出結論:Java 程序設計語言對對象采用的不是引用調用,實際上,對象引用是按值傳遞的。(出自java核心技術卷一,第4章對象與類)
在刷leetcode時看到這樣一道題:
給你一個有序數組 nums ,請你 原地 刪除重復出現的元素,使每個元素 只出現一次 ,返回刪除后數組的新長度。
不要使用額外的數組空間,你必須在 原地 修改輸入數組 並在使用 O(1) 額外空間的條件下完成。
說明:
為什么返回數值是整數,但輸出的答案是數組呢?
請注意,輸入數組是以「引用」方式傳遞的
,這意味着在函數里修改輸入數組對於調用者是可見的。
來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array
著作權歸領扣網絡所有。商業轉載請聯系官方授權,非商業轉載請注明出處。
在編程語言中調用函數時的參數傳遞分為值傳遞和引用傳遞,在學習Java的時候一般會見過這樣一句話:基本數據類型使用值傳遞、對象使用引用傳遞。
對於值傳遞自然好說,傳入方法的是變量的值,比如:
public void raiseSalary(int salary){
salary *= 3; //不會影響傳入變量的值
}
salary接收的變量在傳入函數時會拷貝一份傳入變量作為副本,這個副本是一個值相同的新變量,之后對這個新變量的任何操作都不會影響原變量的值,也就是說上面的這個提升工資方法是無效的。
那么為什么傳入的數組對象,對其進行修改會影響原來的值呢?
首先,我們應該區分變量和對象的概念,簡單地的說int[] a,a是一個數組變量。而new出來的就是一個對象。數組顯然是一個對象。
int[] a = new int[]{1, 2, 3} //變量a引用了一個數組對象,a存儲的值實際是數組對象的地址。
在Java核心技術中已經告知,對象引用是按值傳遞的
,即傳入的對象變量也會對值進行拷貝。只不過引用變量類型的值就是引用的對象的地址,拷貝的變量的值也就是相當於把這個地址拷貝了一遍。即原變量和拷貝變量都會根據這個地址指向一個對象,所以修改這個對象,兩個變量自然都可以感知到了。
因此輸入數組是以「引用」方式傳遞的這句話是不對的,下面的例子可以證明:
public static void main(String[] args){
int[] arrayA = new int[]{1,2,3};
int[] arrayB = new int[]{4,5,6};
System.out.println("交換前:"+Arrays.toString(arrayA)+" "+Arrays.toString(arrayB));
swapArray(arrayA,arrayB);
System.out.println("交換后:"+Arrays.toString(arrayA)+" "+Arrays.toString(arrayB));
}
public static void swapArray(int[] a,int[] b){
int[] c = a;
a = b;
b = c;
System.out.println("交換方法:"+Arrays.toString(a)+" "+Arrays.toString(b));
}
打印結果:
可以看到因為交換的是拷貝對象的引用,所以對原數組對象引用的交換並沒有成功,可以參考下圖,紅色部分是真正進行的交換:
在大部分情況下,將對象當做引用傳遞可能也可以順利解決問題。可是如果不了解背后的原理在發生錯誤時大概就會一頭霧水了。
最后,貼一下結論:
•一個方法不能修改一個基本數據類型的參數(即數值型或布爾型)。
•一個方法可以改變一個對象參數的狀態。
•一個方法不能讓對象參數引用一個新的對象。