java 引用 string,Java中String通过引用传递问题详细解析

This is a classic question of Java. Many similar questions have been asked on stackoverflow, and there are a lot of incorrect/incomplete answers. The question is simple

if you don’t think too much. But it could be very confusing, if you give more thought

to it.

这是一个非常经典的问题,许多类似的问题在stackoverflow上被提问,有很多不正确或者不完整的回答。如果你不考虑那么多,直接认为string是immutable的,那问题就很简单,如果你想要了解更多细节,问题就变的很复杂。

我们看下面这个非常容易混淆,同时又很经典的代码

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";

}

我们可能以为会输出cd,实际上输出的是ab

这是一个很容易混淆的问题,我们来看一下一个貌似很合理的解释:

x stores the reference which points to the "ab" string in the heap. So when x is passed

as a parameter to the change() method, it still points to the "ab" in the heap like the

following:

变量x存储的是引用,这个引用指向堆上的string“ab”,如下图所示:

d55f378dff06

image.png

所以x传递给change方法的x参数,然后新建一个string“cd”,然后x有指向这个新建的cd变量

d55f378dff06

image.png

这样的解释看上去一点问题没有,但为什么输出的结果又不对呢?

真正的代码执行过程应该是这样的:

When the string "ab" is created, Java allocates the amount of memory required to

store the string object. Then, the object is assigned to variable x, the variable is actually

assigned a reference to the object. This reference is the address of the memory location

where the object is stored.

当string变量‘ab’被创建出来的之后,java分配一块足够大小的内存去存储这个string对象,这个对象被分配给变量x,这个变量x实际上存储的是这个对象在内存中的地址。

The variable x contains a reference to the string object. x is not a reference itself! It

is a variable that stores a reference(memory address).

Java is pass-by-value ONLY. When x is passed to the change() method, a copy of

value of x (a reference) is passed. The method change() creates another object "cd" and

it has a different reference. It is the variable x that changes its reference(to "cd"), not

the reference itself.

这个变量x包含一个这个string对象的一个引用。切记 ** x不是引用本身 **,x只是一个变量存储了一个引用(这个引用其实就是内存的地址)。

java只通过value传递当x被传递给change方法的时候。会将x的一份拷贝传递给change方法中的局部变量x,这是另外一个x,虽然这个x存储的引用也就是地址的值是一样的,待会就被改变了,change方法新建一个对象“cd”,是局部变量里的x指向这个新建cd,所以原本的x还是指向ab。

d55f378dff06

image.png

我们可以测试其他引用类型的传递,会发现他们实际上都是通过值传递的,会在方法里新建一个引用,当我们对这个引用指向一个新对象时就要注意了

import java.util.ArrayList;

import java.util.List;

public class StringTest {

public static void main(String[] args) {

String x = new String("ab");

change(x);

System.out.println(x);

Integer y = new Integer(5);

change(y);

System.out.println(y);

List a = new ArrayList();

a.add(1);

a.add(4);

change(a);

System.out.println(a);

}

public static void change(String x) {

x = "cd";

}

public static void change(Integer y) {

y = 4;

}

public static void change(List a) {

//a.add(5);

a = new ArrayList();

a.add(2);

}

}

输出结果

d55f378dff06

image.png

因为我们在方法中都是新建一个对象,所以局部变量的引用都改变了,无法改变原有的值,所以我们看到三个change方法都没有起到作用。

当我们向方法参数传递一个引用的时候要记住是传递的引用的值,而不是引用本身,当我们不让这个引用指向一个新对象的时候,不会出现问题,当我们在方法中将局部的引用赋给一个new出来的对象,那么我们要切记,这时候这个引用已经指向另一个对象了,它所操作的都不会反映在原有的对象上。

那么我们如何解决上面那个问题呢?

其实很简单,只要不在方法里新建一个对象就行了。保持方法中的那个局部变量的引用也在原有对象上操作

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");

}

我们总结一个关键的问题,Java中没有真正的按引用传递,所有变量都是按值value传递的,引用也是变量,只不过它的值是存的对象的地址。所以引用类型的变量在参数的传递过程中,也会新建一个局部变量,局部变量会得到和引用变量一样的值,也就是指向同一个对象。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值