Java中String是“引用”傳遞


如題,在java中這是一個典型的問題。 在stackoverflow上已經有很多相似的問題被提問,並且有很多不正確或不完整的答案。如果你不往深處想,這是一個很簡單的問題。但如果深入思考,它卻很讓人迷惑。

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";
}

運行它將打印 “ab”.

2. 通常讓人迷惑的解釋如下

在java堆中x存儲指向“ab”的引用。所以當x作為參數傳遞給change()方法時,它在內存中仍然指向“ab”,如下:

string-pass-by-reference

由於java是值傳遞,所以此時x仍然指向“ab”。當chang()方法執行時,它在內存中創建了一個新的String對象“cd”,並且現在x指向“cd”,如下:

string-pass-by-reference 2

上面的解釋看起來非常合理。他們也很清楚java是值傳遞。但是哪里出錯了?

3. 上面的代碼到底如何執行的呢?

上面的解釋有幾處錯誤。跟蹤代碼執行全過程是一個很好的方法,並且理解起來很容易。

當“ab”創建后,java分配對象所需內存空間。然后,變量x指向了“ab”,變量實際上是指向對象的引用。這個引用指向對象存儲的地址。

x保存了一個指向String對象的地址。x不是引用本身!它是保存一個內存地址。

在Java中只有值傳遞。當x通過參數傳遞給change()方法后,x被拷貝了一份。change()創建了另一個對象“cd”,並且x指向了不同的地址空間。實際上是x改變它的引用(指向“cd”),不是x本身。

下圖展示了x在內存的變化

string-pass-by-reference 3

 

4. 錯誤的解釋

上面的問題跟String的不可變沒有關系。即使是StringBuilder,結果也一樣。關鍵是變量存儲的是引用,而不是引用本身!他饒啦

5. 解決問題

如果真的要改變對象的值。首先,對象應該是可變的,如StringBuilder,另外,我們要確認沒有新對象生成並且賦予參數變量,因為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");
}

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM