Java中的值傳遞和地址傳遞(傳值、傳引用)

首先,不要糾結於 Pass By Value 和 Pass By Reference 的字面上的意義,否則很容易陷入所謂的“一切傳引用其實本質上是傳值”這種並不能解決問題無意義論戰中。
更何況,要想知道Java到底是傳值還是傳引用,起碼你要先知道傳值和傳引用的準確含義吧?可是如果你已經知道了這兩個名字的準確含義,那麼你自己就能判斷Java到底是傳值還是傳引用。
這就好像用大學的名詞來解釋高中的題目,對於初學者根本沒有任何意義。

一:搞清楚 基本類型 和 引用類型的不同之處
int num = 10;
String str = "hello";

<img src="https://pic2.zhimg.com/166032bc90958c21604110441ad03f45_b.jpg" data-rawwidth="728" data-rawheight="458" class="origin_image zh-lightbox-thumb" width="728" data-original="https://pic2.zhimg.com/166032bc90958c21604110441ad03f45_r.jpg">如圖所示,num是基本類型,值就直接保存在變量中。而str是引用類型,變量中保存的只是實際對象的地址。一般稱這種變量爲"引用",引用指向實際對象,實際對象中保存着內容。

如圖所示,num是基本類型,值就直接保存在變量中。而str是引用類型,變量中保存的只是實際對象的地址。一般稱這種變量爲"引用",引用指向實際對象,實際對象中保存着內容。

二:搞清楚賦值運算符(=)的作用
num = 20;
str = "java";
<img src="https://pic3.zhimg.com/287c0efbb179638cf4cf27cbfdf3e746_b.jpg" data-rawwidth="714" data-rawheight="572" class="origin_image zh-lightbox-thumb" width="714" data-original="https://pic3.zhimg.com/287c0efbb179638cf4cf27cbfdf3e746_r.jpg">對於基本類型 num ,賦值運算符會直接改變變量的值,原來的值被覆蓋掉。

對於基本類型 num ,賦值運算符會直接改變變量的值,原來的值被覆蓋掉。
對於引用類型 str,賦值運算符會改變引用中所保存的地址,原來的地址被覆蓋掉。但是原來的對象不會被改變(重要)。
如上圖所示,"hello" 字符串對象沒有被改變。(沒有被任何引用所指向的對象是垃圾,會被垃圾回收器回收)

三:調用方法時發生了什麼?參數傳遞基本上就是賦值操作
第一個例子:基本類型
void foo(int value) {
    value = 100;
}
foo(num); // num 沒有被改變

第二個例子:沒有提供改變自身方法的引用類型
void foo(String text) {
    text = "windows";
}
foo(str); // str 也沒有被改變

第三個例子:提供了改變自身方法的引用類型
StringBuilder sb = new StringBuilder("iphone");
void foo(StringBuilder builder) {
    builder.append("4");
}
foo(sb); // sb 被改變了,變成了"iphone4"。

第四個例子:提供了改變自身方法的引用類型,但是不使用,而是使用賦值運算符。
StringBuilder sb = new StringBuilder("iphone");
void foo(StringBuilder builder) {
    builder = new StringBuilder("ipad");
}
foo(sb); // sb 沒有被改變,還是 "iphone"。

重點理解爲什麼,第三個例子和第四個例子結果不同?

下面是第三個例子的圖解:
<img src="https://pic4.zhimg.com/d8b82e07ea21375ca6b300f9162aa95f_b.jpg" data-rawwidth="772" data-rawheight="398" class="origin_image zh-lightbox-thumb" width="772" data-original="https://pic4.zhimg.com/d8b82e07ea21375ca6b300f9162aa95f_r.jpg">builder.append("4")之後builder.append("4")之後
<img src="https://pic4.zhimg.com/ff2ede9c6c55568d42425561f25a0fd7_b.jpg" data-rawwidth="696" data-rawheight="424" class="origin_image zh-lightbox-thumb" width="696" data-original="https://pic4.zhimg.com/ff2ede9c6c55568d42425561f25a0fd7_r.jpg">下面是第四個例子的圖解:下面是第四個例子的圖解:
<img src="https://pic4.zhimg.com/d8b82e07ea21375ca6b300f9162aa95f_b.jpg" data-rawwidth="772" data-rawheight="398" class="origin_image zh-lightbox-thumb" width="772" data-original="https://pic4.zhimg.com/d8b82e07ea21375ca6b300f9162aa95f_r.jpg">
builder = new StringBuilder("ipad"); 之後
<img src="https://pic2.zhimg.com/46fa5f10cc135a3ca087dae35a5211bd_b.jpg" data-rawwidth="710" data-rawheight="438" class="origin_image zh-lightbox-thumb" width="710" data-original="https://pic2.zhimg.com/46fa5f10cc135a3ca087dae35a5211bd_r.jpg">

作者:Intopass
鏈接:https://www.zhihu.com/question/31203609/answer/50992895
來源:知乎
著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。


Java傳遞參數有兩種方式:值傳遞和引用傳遞
值傳遞是傳遞數據:如基本數據類型都是值傳遞
引用傳遞是把形參和實參的指針指向了堆中的同一對象,對象的引用和數組的引用。

實參,Java的基本數據類型,如int,double等在函數的參數傳遞時,傳遞的是副本。String也屬於這一範疇。

形參,而如果是對象,則傳遞的是引用。




作者:fbysss
msn:[email protected]  
blog:blog.csdn.net/fbysss
聲明:本文由fbysss原創,轉載請註明出處
關鍵字:Java 傳值 傳引用

這是個老生常談的問題了,引起過無數爭論,但可以說一直沒有一個令人滿意的回答。

有些人非要故弄玄虛,把傳引用說成是棧裏面放的是引用的值,說只有傳值沒有傳引用,那看看這句經典名言吧:

O'Reilly's Java in a Nutshell by David Flanagan (see Resources) puts it best: "Java manipulates objects 'by reference,' but it passes object references to methods 'by value.'"

從這裏也可以看到,David 也沒那麼生硬,不過是看你從哪個角度來認識這個問題,如果大家習慣c++的那種傳參時的理解方式,爲何不能這麼比較呢?

有人已經總結過:

參見

http://www.javaresearch.org/article/3156.htm

1、對象是按引用傳遞的
2、Java 應用程序有且僅有的一種參數傳遞機制,即按值傳遞
3、按值傳遞意味着當將一個參數傳遞給一個函數時,函數接收的是原始值的一個副本
4、按引用傳遞意味着當將一個參數傳遞給一個函數時,函數接收的是原始值的內存地址,而不是值的副本
寫的沒錯,但是文字太多,第二條就已經把人弄糊塗了,得仔細看完4條才清楚。而且對String類型的疑惑沒有解決。

這麼簡單的事情,何必這麼繞呢?爲啥沒人跟c++過不去,偏要跟Java來勁?

三句話總結一下:

1.對象就是傳引用

2.原始類型就是傳值

3.String等immutable類型因爲沒有提供自身修改的函數,每次操作都是新生成一個對象,所以要特殊對待。可以認爲是傳值。

其他參考文章:

http://www-128.ibm.com/developerworks/cn/java/l-jpointer/index.html

http://dreamhead.blogbus.com/logs/2005/05/1189478.html

http://www.javaeye.com/topic/12961



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章