原文链接:点击这里
1、先来一段代码:
public class StringValue {
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、不应该输出 cd 吗?
x存储指向堆中“ab”字符串的引用。因此,当x作为参数传递给change()方法时,它仍然指向堆中的“ab”,如下所示:
因为java是按值传递,所以x的值是对ab的引用。当调用方法change()时,它会创建一个新的cd对象,而x现在指向cd。如下所示:
这么解释,似乎没毛病!
3、这段代码到底做了什么?
创建字符串ab时,Java会分配存储字符串ab对象所需的内存量。然后将对象分配给变量x,实际上x被赋予对象的内存地址
变量x包含对字符串对象的引用。x本身是一个存储ab内存地址的变量。
Java只是按值传递。当x传递给change()方法时,将传递x(引用)值的副本。方法change()创建另一个对象cd,它有一个不同的引用地址。然后更改变量x其地址为cd,而没有改变原先引用的字符串ab的地址。如图:
个人理解:假如老王现在在荷兰【x】,公司人事听成了河南【change(x)】。但其实老王人一直在荷兰!
4、错误的解释
从第一个代码片段引发的问题与字符串不变性无关。即使String被StringBuilder替换,结果仍然相同。关键是变量存储引用地址,但不是引用本身!
5、问题解决
如果我们真的需要改变对象的值。首先,对象应该是可更改的,例如StringBuilder。其次,我们需要确保没有创建新对象并将其分配给参数变量,因为Java只是按值传递。
public class StringValue {
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");
}
}