在Java中,當對象做爲參數傳遞時,究竟傳遞的是對象的值,仍是對象的引用,這是一個飽受爭議的話題。若傳的是值,那麼函數接收的只是實參的一個副本,函數對形參的操做並不會對實參產生影響;若傳的是引用,那麼此時對形參的操做則會影響到實參。
首先咱們來看一句代碼:app
Object obj = new Object();
這句話的意思是:建立一個Object對象,再建立一個名爲obj的引用,讓這個引用指向這個對象,以下圖所示:函數
在有了上面的基礎以後,咱們便來看下面這組在網上很流行的例子:spa
例1:.net
public class test { public static void main(String[] args) { int i = 1; System.out.println("before change, i = "+i); change(i); System.out.println("after change, i = "+i); } public static void change(int i){ i = 5; } }
這個例子不難理解,當基本數據類型(Boolean,byte,char,String,int,Long,float,double)做爲參數傳遞時,傳遞的是實參值的副本,即傳的是值,不管在函數中怎麼操做這個副本,實參的值是不會被改變的。因此以上代碼執行的結果是:
3d
before change, i = 1
after change, i = 1
在下面的例2中,咱們把StringBuffer對象做爲參數傳遞到change函數。
例2:code
public class test { public static void main(String[] args) { StringBuffer sb = new StringBuffer("Hello "); System.out.println("before change, sb is "+sb.toString()); change(sb); System.out.println("after change, sb is "+sb.toString()); } public static void change(StringBuffer stringBuffer){ stringBuffer.append("world !"); } }
爲了方便推理出結論,咱們先直接看程序的運行結果:
對象
before change, sb is Hello
after change, sb is Hello world !
從輸出結果中咱們能夠發現,sb所指向的對象的值被改變了,那麼是否咱們能夠推論出,在Java中,當對象做爲參數傳遞時,傳遞的是該對象的引用呢?咱們再來看下面這個例子: blog
public class test { public static void main(String[] args) { StringBuffer sb = new StringBuffer("Hello "); System.out.println("before change, sb is "+sb.toString()); change(sb); System.out.println("after change, sb is "+sb.toString()); } public static void change(StringBuffer stringBuffer){ stringBuffer = new StringBuffer("Hi "); stringBuffer.append("world !"); } }
若是上面的推論是正確的,即Java中對象做爲參數傳遞,實際傳遞的是該對象的引用,那麼在調用change函數以後,原對象的值應該是會改變的,變爲「Hi world !」,可是,當咱們運行程序後,結果倒是以下所示:
內存
before change, sb is Hello
after change, sb is Hello
原對象的值並無被改變,這與上面的推論相矛盾!爲何在Java中,當對象做爲參數傳遞時,有的時候實參被改變了,而有的時候實參並未被改變呢?下面讓咱們來分析一下其中的緣由:
從文章的開頭咱們知道,當執行StringBuffer sb = new StringBuffer(「Hello 「)時,咱們建立了一個指向新建對象「new StringBuffer(「Hello 「)」的引用「sb」,以下圖所示: string
在例2中,當咱們調用change函數後,實際上,形參stringBuffer也指向了實參sb所指向的對象,即:
那麼當咱們執行stringBuffer.append(「world !」)後,便經過對象的引用「stringBuffer」修改了對象的值,使之變成了「Hello world !」,即:
可是,在例3中的change函數中,咱們又新建了一個對象「new StringBuffer(「Hi 「)」(這實際上在內存中開闢了一塊在原對象地址以外的新區域),這讓形參stringBuffer實際指向了這個新建的對象,並將新對象的值設置爲「Hi world !」,例三中stringBuffer的值已經被改變爲了Hi world,可是由於值沒有被return返回賦值給sb對象,因此sb對象並無被改變,因此輸出的任然是hello,即:
那麼咱們就不難理解,爲什麼在執行完change函數以後,實參的值仍爲「Hello」了。
綜上所述,咱們能夠得出結論:在Java中,當對象做爲參數傳遞時,實際上傳遞的是一份「引用的拷貝」。 (實際傳遞的是對象的引用)
轉載自:https://blog.csdn.net/xiangwanpeng/article/details/52454479