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万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章