Java基础——详解Java中的String参数传递

【申明:以下内容翻译自http://www.programcreek.com/java-tutorials/ , 欢迎转载,请勿用于商业用途】



欢迎阅读原文:String is passed by “reference” in Java


这是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()时,x仍然指向堆中的字符串“ab”,如下图所示:


由于Java中是值传递——x的值是“ab”的引用,当change()方法被调用后,创建了一个字符串“cd”对象,并且x现在指向了“cd”,当前状态如下图所示:


这看上去是一个相当合理的解释。他们明确的知道java是值传递。但是,他们错在了哪里?


3、那段代码真正做了什么事?

以上的解释有几个误区。为了更容易了理解该问题,看完下面的内容是不错的选择。


当字符串“ab”被创建后 ,Java分配字符串对象需要的存储空间。然后将该字符串对象指定给变量x,实际上指定的是对象的引用(该引用是存储对象的内存的地址)。

变量x包含了字符串对象的引用。x不是引用本身,而是一个存储了引用(内存地址)的变量。

Java中只有值传递。当x作为参数传递给change()方法时,实际上传递的是x值得一个拷贝。方法change()创建了另一个字符串对象“cd”(有一个不同的引用——内存地址)。此时是变量x改变了它的引用,而不是变量x本身。下图展示了真正所做的事



4、错误的解释

从以上代码片段中提出的问题跟String的不变性没有任何关系,即是换做StringBuiler也是一样的。关键点是变量存储了对象的引用(内存地址),但不是自己的引用(内存地址)。


5、解决方案

如果我们真的想要改变对象的值,首先,保证对象是可改变的(比如:StringBuiler);其次没有新的对象创建并赋值给参数(因为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");
}

补充:上文第3点讲到了代码真正做的事,开始个人了很久也感觉还是模模糊糊的,后来经一位前辈的指点才算是彻底明白了(在此感谢cracker.li的帮助),以下用结合幅图来阐述自己的理解。为了便于理解在方法change(x)时,写了一句x' = x ;


在上图中左下面表示“栈”,代码 x=“ab” ; 让x指向堆中字符串“ab”。调用方法change()时,创建了一个x的副本x' 。在未改变x'时,x'一直指向字符串“ab”。



change()方法中执行代码x="cd",此时x’断开到“ab”的指向(引用地址改变),x‘指向"cd"(因为Java只有值传递)。

在此,x‘相当于一个匿名对象。由于Java只有值传递,所以在 x'=x ; 的时候,他们任何变量的内容的改变就互不影响了。




  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值