JAVA中的值傳遞和引用傳遞

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

一:搞清楚 基本類型 和 引用類型的不同之處

int num = 10;
String str = "hello";

圖片說明

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

二:搞清楚賦值運算符(=)的作用

num = 20;
str = "java";

對於基本類型 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"。

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

下面是第三個例子的圖解:
圖片說明
builder.append("4")之後
圖片說明
下面是第四個例子的圖解:
圖片說明
builder = new StringBuilder("ipad"); 之後
圖片說明

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

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