译文路径: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
原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/13789.html