前言
在Java中,當對象作為參數傳遞時,究竟傳遞的是對象的值,還是對象的引用,這是一個飽受爭議的話題。若傳的是值,那么函數接收的只是實參的一個副本,函數對形參的操作並不會對實參產生影響;若傳的是引用,那么此時對形參的操作則會影響到實參。
首先我們來看一句代碼:
Object obj = new Object();
這句話的意思是:創建一個Object對象,再創建一個名為obj的引用,讓這個引用指向這個對象,如下圖所示:
在有了上面的基礎之后,我們便來看下面這組在網上很流行的例子:
基本數據類型作為參數傳遞:
例1:
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)作為參數傳遞時,傳遞的是實參值的副本,即傳的是值,無論在函數中怎么操作這個副本,實參的值是不會被改變的。所以以上代碼執行的結果是:
before change, i = 1
after change, i = 1
對象作為參數傳遞:
在下面的例2中,我們把StringBuffer對象作為參數傳遞到change函數。
例2:
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中,當對象作為參數傳遞時,傳遞的是該對象的引用呢?我們再來看下面這個例子:
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”,如下圖所示:
在例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