Java中的字符串属于引用传递?

原文:String is passed by “reference” in Java

这是Java中的一个经典问题,在Stack Overflow上有许多相似的问题,有些是错误的或并不完整的回答。如果你不考虑许多情况这问题是简单的。但如果你考虑更多的情况,它可能是令人困惑的。

一个令人感兴趣且令人困惑的代码片段

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

常见的令人困惑的问题
变量x中存储着指向堆中字符串ab的引用,当变量x作为change()调用时的参数时,它仍然指向堆中的字符串ab,如图:
这里写图片描述

因Java中是值传递,变量x的值为字符串ab的引用。当change()被调用时,它创建一个新对象cd,使变量x指向cd
这里写图片描述

这似乎是一个相当合理的解释。这是明显的-Java总是值传递。但这里什么是错误的呢?

这段代码实际做了什么?
这解释显然有些错误,为了很容易理解这一点,在整个过程中简单地走一走是个好主意。
当字符串ab被创建,Java分配必要的内存空间存储字符串对象。然后,这对象被分配给到变量x,实际上变量x被指定为对象的引用。这引用是这个对象被保存在内存中的地址。
变量x包含一个指向字符串对象的引用, 变量x不是它自身的引用。它是一个存储内存地址引用的变量。
Java仅支持值传递。当变量x被传递到change()中时,传递的是变量x的值的副本。change()创建另一个对象cd,它有一个不同的引用。变量x改变它的引用指向cd,而不是引用本身。
这里写图片描述

错误的解释
第一个代码片段中提出的问题与字符串是不可变的无任何关系。即使将String替换为StringBuilder,这结果也是相似的。
这关键点是这变量存储的是引用,而不是引用本身。

解决问题
如果我们真的需要改变对象的值。首先,这对象应该是可改变的,例如: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");
}

这篇文章的重点不在于值传递引用传递之争,而是理解清楚第一段代码中,程序实际上做了哪些操作?是如何操作的?

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值