Java String對象以“引用”方式被傳遞

譯文路徑:String is passed by “reference”in Java


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

在C++中,代碼如下

void change(string &x) {
    x = "cd";
}
 
int main(){
    string x = "ab";
    change(x);
    cout << x << endl;
}

打印結果:cd

 

2、常見的困惑問題


x存儲指向堆中的“ab”字符串的引用。所以,當x被作爲參數傳遞到change()方法時,它仍然指向堆中“ab”,像下面這樣:


 
因爲java是按值傳遞的(pass-by-value), x的值是“ab”的引用。當方法的change()被調用,它會創建一個新的“cd”的對象,而x現在是指向“cd”像下面這樣:


 
這似乎是一個相當合理的解釋。他們明確表示,Java是總是傳遞按值。但是,錯在哪裏呢?


3、代碼真正做了些什麼呢?


上面的解釋有幾個錯誤。爲了容易理解這一點,這是一個好主意,簡單地描述整個過程。
當字符串“ab”被創建,java分配存儲字符串對象所需的內存空間。然後,將對象分配給變量x,該變量是被實際分配的引用對象。此引用是該對象被存儲在內存的地址。
變量x包含一個字符串對象的引用。 x不是引用本身!它是用於存儲一個引用(內存地址)的變量。
Java是僅僅是按值傳遞。當x傳遞給change()方法,x的(引用)值的副本被傳遞。方法change()創建另一個對象“cd”,它有一個不同的引用。它是被改變的x副本指向“cd”的變量,而不是x引用本身。
下面的圖表展現了真實的過程:


 
4、錯誤的解釋


從第一個代碼片段中所提出的問題是沒有聯繫到String對象的不變性。即使字符串被替換StringBuilder的,結果還是一樣。關鍵的一點是,變量存儲的是引用,而不是引用本身!

5、這個問題的解決方法


如果我們真的需要改變對象的值。首先,對象應該是可變的,例如,StringBuilder對象。其次,我們需要確保沒有創建新的對象並將此對象分配給參數變量,因爲Java是隻是按值傳遞(passing-by-value)。

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


Related posts:

  1. Yet Another “Java Passes By Reference or By Value”?
  2. Notes from “Sun Certified Programmer for Java 6 Study Guide”
  3. Diagram to show Java String’s Immutability
  4. Overriding and overloading in Java with examples




發佈了87 篇原創文章 · 獲贊 224 · 訪問量 96萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章