Java的字符串是值傳遞還是引用傳遞
Java的字符串是值傳遞還是引用傳遞
這是Java的經(jīng)典問題。關于stackoverflow,已經(jīng)提出了許多類似的問題,并且有很多不正確/不完整的答案。如果您考慮不多,問題很簡單。但是,如果您對此進行更多考慮,可能會造成混亂。
1. 一個有趣且令人困惑的代碼片段
public?static?void?main(String[]?args)?{
?String?x?=?new?String("ab");
?change(x);
?System.out.println(x);
}
?
public?static?void?change(String?x)?{
?x?=?"cd";
}
得出來的結(jié)果
ab
在C ++中,代碼如下:
void?change(string?&x)?{
????x?=?"cd";
}
?
int?main(){
????string?x?=?"ab";
????change(x);
????cout?<}
得到的結(jié)果
cd
2. 常見的令人困惑的問題
x存儲指向堆中"ab"字符串的引用。因此,當x作為參數(shù)傳遞給change()方法時,它仍指向堆中的"ab",如下所示:
因為java是傳遞值,所以x的值是對"ab"的引用。當方法change()被調(diào)用時,它將創(chuàng)建一個新的"cd"對象,并且x現(xiàn)在指向"cd",如下所示:

這似乎是一個很合理的解釋。他們很清楚Java總是按值傳遞。但是這里有什么問題?
3. 代碼實際上是做什么的?
上面的解釋有幾個錯誤。為了輕松理解這一點,最好簡要介紹一下整個過程。
創(chuàng)建字符串"ab"時,Java會分配存儲字符串對象所需的內(nèi)存量。然后,該對象被分配給變量x,該變量實際上被分配了對該對象的引用。該引用是存儲對象的存儲位置的地址。
變量x包含對字符串對象的引用。x本身不是參考!它是一個存儲引用(內(nèi)存地址)的變量。
Java僅按值傳遞。將x傳遞給change()方法時,將傳遞x值的副本(引用)。方法change()創(chuàng)建另一個對象"cd",并且它具有不同的引用。是變量x更改其引用(改為"cd"),而不是引用本身。
下圖顯示了它的實際作用。

4.錯誤的解釋
第一個代碼片段引起的問題與字符串不變性無關。即使將String替換為StringBuilder,結(jié)果仍然相同。關鍵是變量存儲引用,但不是引用本身!
5.解決這個問題
如果真的需要更改對象的值。首先,對象應該是可變的,例如StringBuilder。其次,我們需要確保沒有創(chuàng)建新對象并將其分配給參數(shù)變量,因為Java僅按值傳遞。
public?static?void?main(String[]?args)?{
?StringBuilder?x?=?new?StringBuilder("ab");
?change(x);
?System.out.println(x);
}
?
public?static?void?change(StringBuilder?x)?{
?x.delete(0,?2).append("cd");
}
