前言
在Java中右冻,當對象作為參數(shù)傳遞時装蓬,究竟傳遞的是對象的值,還是對象的引用国旷,這是一個飽受爭議的話題矛物。若傳的是值,那么函數(shù)接收的只是實參的一個副本跪但,函數(shù)對形參的操作并不會對實參產(chǎn)生影響履羞;若傳的是引用峦萎,那么此時對形參的操作則會影響到實參。
首先我們來看一句代碼:
Object obj = new Object();
1
這句話的意思是:創(chuàng)建一個Object對象忆首,再創(chuàng)建一個名為obj的引用爱榔,讓這個引用指向這個對象,如下圖所示:
在有了上面的基礎之后糙及,我們便來看下面這組在網(wǎng)上很流行的例子:
基本數(shù)據(jù)類型作為參數(shù)傳遞:
例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;
}
}
1
2
3
4
5
6
7
8
9
10
11
這個例子不難理解详幽,當基本數(shù)據(jù)類型作為參數(shù)傳遞時,傳遞的是實參值的副本浸锨,即傳的是值唇聘,無論在函數(shù)中怎么操作這個副本,實參的值是不會被改變的柱搜。所以以上代碼執(zhí)行的結果是:
before change, i = 1
after change, i = 1
對象作為參數(shù)傳遞:
在下面的例2中迟郎,我們把StringBuffer對象作為參數(shù)傳遞到change函數(shù)。
例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 !");
}
}
1
2
3
4
5
6
7
8
9
10
11
為了方便推理出結論聪蘸,我們先直接看程序的運行結果:
before change, sb is Hello
after change, sb is Hello world !
從輸出結果中我們可以發(fā)現(xiàn)宪肖,sb所指向的對象的值被改變了,那么是否我們可以推論出健爬,在Java中控乾,當對象作為參數(shù)傳遞時,傳遞的是該對象的引用呢娜遵?我們再來看下面這個例子:
例3:
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 !");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
如果上面的推論是正確的蜕衡,即Java中對象作為參數(shù)傳遞,實際傳遞的是該對象的引用魔熏,那么在調(diào)用change函數(shù)之后衷咽,原對象的值應該是會改變的,變?yōu)椤癏i world 蒜绽!”镶骗,但是,當我們運行程序后躲雅,結果卻是如下所示:
before change, sb is Hello
after change, sb is Hello
原對象的值并沒有被改變鼎姊,這與上面的推論相矛盾!為什么在Java中相赁,當對象作為參數(shù)傳遞時相寇,有的時候?qū)崊⒈桓淖兞耍械臅r候?qū)崊⒉⑽幢桓淖兡嘏タ疲肯旅孀屛覀儊矸治鲆幌缕渲械脑颍?br>
從文章的開頭我們知道唤衫,當執(zhí)行StringBuffer sb = new StringBuffer(“Hello “)時,我們創(chuàng)建了一個指向新建對象“new StringBuffer(“Hello “)”的引用“sb”绵脯,如下圖所示:
在例2中佳励,當我們調(diào)用change函數(shù)后休里,實際上,形參stringBuffer也指向了實參sb所指向的對象赃承,即:
那么當我們執(zhí)行stringBuffer.append(“world !”)后妙黍,便通過對象的引用“stringBuffer”修改了對象的值,使之變成了“Hello world 瞧剖!”拭嫁,即:
但是,在例3中的change函數(shù)中抓于,我們又新建了一個對象“new StringBuffer(“Hi “)”(這實際上在內(nèi)存中開辟了一塊在原對象地址之外的新區(qū)域)做粤,這讓形參stringBuffer實際指向了這個新建的對象,并將新對象的值設置為“Hi world 毡咏!”驮宴,即:
那么我們就不難理解逮刨,為何在執(zhí)行完change函數(shù)之后呕缭,實參的值仍為“Hello”了。
結論
綜上所述修己,我們可以得出結論:在Java中恢总,當對象作為參數(shù)傳遞時,實際上傳遞的是一份“引用的拷貝”睬愤。
作者:Alan_Xiang
來源:CSDN
原文:https://blog.csdn.net/xiangwanpeng/article/details/52454479
版權聲明:本文為博主原創(chuàng)文章片仿,轉(zhuǎn)載請附上博文鏈接!