譯文路徑: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:
- Yet Another “Java Passes By Reference or By Value”?
- Notes from “Sun Certified Programmer for Java 6 Study Guide”
- Diagram to show Java String’s Immutability
- Overriding and overloading in Java with examples