關(guān)于Java的參數(shù)傳遞,是一個老生常談的問題了,引用傳遞、值傳遞傻傻的分不清楚是許多程序員經(jīng)常遇到的問題,那么今天就來聊聊Java中的參數(shù)傳遞。
先來看個例子:
public static void main(String[] args) {
int[] arr = {3,4,5,6};
int num = 5;
changearr(arr);
changenum(num);
System.out.println("arr[0] = " + arr[0]);
System.out.println("num = " + num);
}
public static void changearr(int[] arr) {
arr[0] = 1;
}
public static void changenum(int num) {
num = 1;
}
結(jié)果:
arr[0] = 1
num = 5
分析
從上面代碼的運行結(jié)果不難發(fā)現(xiàn),在傳遞基本類型時,方法內(nèi)部并不能改變方法外的變量,而引用類型則會被改變。
那么Java倒底是用的值傳遞還是引用傳遞呢?
在《Head First Java》里面曾解釋過:
Java在調(diào)用方法,傳遞參數(shù)的時候,采用的是pass-by-copy的方法,傳遞一份內(nèi)容的拷貝,即傳值。
所以說Java用的應(yīng)該是值傳遞,那么為什么會出現(xiàn)上面的情況呢?
這就涉及到Java中的兩種數(shù)據(jù)類型了:引用類型和基本類型。
1.基本數(shù)據(jù)類型
Java中一共分為8種基本數(shù)據(jù)類型:byte、short、int、long、float、double、char、boolean,其中byte、short、int、long是整型。float、double是浮點型,char是字符型,boolean是布爾型。
上面這段話相信學(xué)過Java的人都看過,隨便一本講Java的書都應(yīng)該有。
2.引用數(shù)據(jù)類型
Java中有3種引用類型:class類 、interface接口 、array數(shù)組。
基本類型和引用類型的區(qū)別
下面關(guān)鍵點來了,上面兩種數(shù)據(jù)類型的區(qū)別在哪呢?
基本數(shù)據(jù)類型的變量是存儲在棧內(nèi)存中,而引用類型變量存儲在棧內(nèi)存中,保存的是實際對象在堆內(nèi)存中的地址,實際對象其實是在堆上的。
啥是堆和棧?如果這都區(qū)分不清楚的話,建議還是去看看JVM內(nèi)存相關(guān)的知識,這里就不詳細(xì)說了。
看到這里應(yīng)該能明白為什么會出現(xiàn)例子中的情況了吧。
首先,Java確確實實是傳值(pass-by-value)的,在上面的例子里,傳過去的確確實實也是一個值的copy,但是引用型(Reference Type)變量里面存放的值是對象的地址,那么傳遞過去的就是原對象的地址。也就是說,在方法中的數(shù)組指向的地址和原數(shù)組指向的地址是一樣的,而我們對數(shù)組操作時是操作數(shù)組指向的地址段中的內(nèi)容,方法內(nèi)和方法外操作的是同一段內(nèi)存,那么自然改變也是同步的。
好像還是不大好理解,看看《Head First Java》里面的電視機(jī)和遙控器的例子吧:
引用類型的對象就相當(dāng)于一個電視機(jī)和遙控器,我們傳遞的時候是復(fù)制了一個一摸一樣的遙控器,因此,盡管新舊兩個遙控器不是同一個對象,但是兩個遙控器都可以控制電視,新遙控器換臺,電視機(jī)一樣會響應(yīng)。
而基本類型的對象則相當(dāng)于只有一個遙控器,我們傳遞的時候依舊是復(fù)制了一個一摸一樣的遙控器,就算我們把新的遙控器拆掉,原來的遙控器也不會受到絲毫影響。