引言
學(xué)習(xí)過C語言的同學(xué)都很清楚在c中調(diào)用方法的參數(shù)有值傳遞和引用傳遞兩種方式。關(guān)于值傳遞和引用傳遞網(wǎng)上有許多的博客寫的很好,這里我就不解釋了。附上一篇:值傳遞和引用傳遞。但是使用過Java的同學(xué)可能知道,如果我們按照C語言的參數(shù)傳遞方式來理解Java中參數(shù)傳遞的話,有時候可能會和自己預(yù)料的答案有所出入。
Java中的參數(shù)傳遞方式
值傳遞
Java中的值傳遞指得是Java所提供的八種基本數(shù)據(jù)類型,不包括他們相應(yīng)的包裝類。
public class ReferTest {
public static void main(String[] args){
int data = 20;
int res = basic(data);
System.out.println("main:result data = " + res);
System.out.println("main:data = " + data);
}
/**
* 基本數(shù)據(jù)類型測試
*/
public static int basic(int data){
data = 25;
System.out.println("basic:data = " + data);
return data;
}
上面的代碼是對基本數(shù)據(jù)類型傳遞的測試,在main方法中定義一個int型的數(shù),在basic方法中對改值進(jìn)行修改后返回,然后分別打印到控制臺。
basic:data = 25
main:result data = 25
main:data = 20
由打印結(jié)果我們可以看到有參數(shù)傳到basic中的data已經(jīng)在basic中被改變,并且也返回了被改變的數(shù)據(jù),但是data本身這個數(shù)并沒有改變,這說明,基本數(shù)據(jù)類型時通過值傳遞,main方法中的data和basic方法中的參數(shù)data并不是同一個。
引用傳遞
引用傳遞是指我們在傳遞參數(shù)的時候傳遞的是對象的引用而不是值,在Java中能被稱為引用的包括使用各種方法(new,反射)創(chuàng)建的對象,數(shù)組等。這里需要注意的是String是一個類而不是基本數(shù)據(jù)類型,他的實例是一個對象。
public static void main(String[] args){
int[] arrs ={10,6,4,8};
ReferTest.sort(arrs);
System.out.println("main:");
for (int index:arrs) {
System.out.print(index + " ");
}
}
public static void sort(int[] arrs){
Arrays.sort(arrs);
System.out.println("sort:");
for (int index:arrs) {
System.out.print(index + " ");
}
System.out.println();
}
這里使用數(shù)組來測試,首先創(chuàng)建了一個無序數(shù)組,將該數(shù)組作為參數(shù)傳遞到sort()方法中,調(diào)用api排序。
sort:
4 6 8 10
main:
4 6 8 10
可以看到結(jié)果中不僅sort()中的數(shù)組已經(jīng)被排序,main()中的數(shù)組也已經(jīng)排序,在這個測試中,我們并沒有指定返回值。這個結(jié)果和預(yù)期引用傳遞參數(shù)的方式一樣,那么這個測試能否說明Java和c++等方法一樣既有值傳遞又有引用傳遞呢?
繼續(xù)測試
public static void main(String[] args){
int[] arrs ={10,6,4,8};
ReferTest.sort(arrs);
System.out.println("main:");
for (int index:arrs) {
System.out.print(index + " ");
}
}
public static void sort(int[] arrs){
int[] testArr = {9,4,2,7};
arrs = testArr;
Arrays.sort(arrs);
System.out.println("sort:");
for (int index:arrs) {
System.out.print(index + " ");
}
System.out.println();
}
我在sort()中又創(chuàng)建了一個數(shù)組,內(nèi)容和參數(shù)數(shù)組完全不同,然后將此數(shù)組賦值給參數(shù)數(shù)組,如果是引用傳遞的話,那么在main()中的數(shù)組也將變成testArr。
sort:
2 4 7 9
main:
10 6 4 8
然后結(jié)果和我們期望的并不一樣,這里sort()中數(shù)組已經(jīng)被賦值并且排序過了,但是main中的依然是之前的值,而且未經(jīng)過排序。那么很明顯Java中并不是使用的同c++一樣的引用排序。
解釋
在Java中,引用傳遞實際上不是傳遞的該引用本身,而是傳遞的該引用的一個副本,如果不對副本指向進(jìn)行修改,那么這個副本和引用值就是同一個地址,操作副本就相當(dāng)于操作引用,這里就和引用傳遞一致了。但是如對該副本修改了指向,那么修改的知識副本值,而不會對引用本身造成影響。
arrs = testArr;
當(dāng)程序走到這一步之前,大概是這樣的。圖只是為了方便理解,但是內(nèi)存中實際不是這樣的。

形參和實參指向同一片地址,這里就可以成為引用傳遞。而賦值過程完成后就成了這樣

形參的指向被改變了,指向的地址變化,這時候形參和實參已經(jīng)沒有了任何關(guān)系。對形參的任何修改都不會反映到實參中。
其實Java中對象到底是值傳遞或引用傳遞沒必要一定要在理論上確定一個答案,只要弄明白它的運(yùn)行原理,在使用中根據(jù)原理來合理的編寫代碼就可以了。