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 String对象以“引用”方式被传递详解编程语言
 
因为java是按值传递的(pass-by-value), x的值是“ab”的引用。当方法的change()被调用,它会创建一个新的“cd”的对象,而x现在是指向“cd”像下面这样:

Java String对象以“引用”方式被传递详解编程语言
 
这似乎是一个相当合理的解释。他们明确表示,Java是总是传递按值。但是,错在哪里呢?

3、代码真正做了些什么呢?


上面的解释有几个错误。为了容易理解这一点,这是一个好主意,简单地描述整个过程。
当字符串“ab”被创建,java分配存储字符串对象所需的内存空间。然后,将对象分配给变量x,该变量是被实际分配的引用对象。此引用是该对象被存储在内存的地址。
变量x包含一个字符串对象的引用。 x不是引用本身!它是用于存储一个引用(内存地址)的变量。
Java是仅仅是按值传递。当x传递给change()方法,x的(引用)值的副本被传递。方法change()创建另一个对象“cd”,它有一个不同的引用。它是被改变的x副本指向“cd”的变量,而不是x引用本身。
下面的图表展现了真实的过程:

Java String对象以“引用”方式被传递详解编程语言
 
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




原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/13789.html

(0)
上一篇 2021年7月19日
下一篇 2021年7月19日

相关推荐

发表回复

登录后才能评论