首页 > 代码库 > 通过引用传递字符串
通过引用传递字符串
这是一个经典问题。有很多类似的问题在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是值传递的,所以x的值是指向”ab“的引用。当方法change()被调用时,它会创建一个新的对象”cd“。现在x指向”cd“,像下图这样:
这似乎是一个令人信服的解释。这完全符合Java总是通过值传递的结论。但是哪里出错了呢?
3.这段代码到底如何工作的
上面的解释有几处错误。为了更好的理解,我们简单介绍一下整个过程。
当字符串”ab“被创建的时候,Java分配了可以存储这个字符串大小的内存,这个字符串对象赋值给变量x,变量x实际上获得了指向这个对象的引用。这个引用是字符串对象存储在内存中的地址。
变量x包含指向这个字符串对象的引用。x本身并不是一个引用。它是存储一个引用的变量。
Java仅存在值传递。当x被传递给方法change()时,传递给这个方法的是x的一份拷贝。change()方法创建了另外一个对象cd,有一个不同引用指向它。变量x改变了指向字符串对象”cd“的引用,而不是引用本身。
下图向我们展示了事情的真相。
4.错误的解释
上面的代码片段引出的问题与字符串的不可变性没有关系。即使用StringBuilder代替String,结果也是相同的。问题的关键是那个变量存储了引用,但它不是引用本身。
5.如何避免上面的问题
如果我们确实需要改变对象的值。首先,这个对象可以被改变,比如StringBuilder。第二,我们需要确保不会有新的对象被创建,然后赋给参数变量。因为Java是值传递的。
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"); }
通过引用传递字符串
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。