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

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

4.錯(cuò)誤的解釋
第一個(gè)代碼片段引起的問(wèn)題與字符串不變性無(wú)關(guān)。即使將String替換為StringBuilder,結(jié)果仍然相同。關(guān)鍵是變量存儲(chǔ)引用,但不是引用本身!
5.解決這個(gè)問(wèn)題
如果真的需要更改對(duì)象的值。首先,對(duì)象應(yīng)該是可變的,例如StringBuilder。其次,我們需要確保沒(méi)有創(chuàng)建新對(duì)象并將其分配給參數(shù)變量,因?yàn)镴ava僅按值傳遞。
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");
}
