Java更改引用但不更改对象本身?

时间:2015-01-30 17:41:59

标签: java variable-assignment pass-by-reference

请参阅以下代码:

public static void main(String[] args)
{
    Test t1 = new Test();
    t1.i = 1;
    Test t0 = t1;
    Test t2 = new Test();
    t2.i = 2;
    t0 = t2; 
    System.out.println(t1.i); //prints 1, I thought it would print 2
}

有没有办法在我从其他地方通过简单的赋值而不直接访问t1来更改t1对象? (即t1 = t0)

3 个答案:

答案 0 :(得分:2)

以下是您的计划及其功能的说明。系统的每个状态都以虚线分隔。

注意执行t0 = t1时会发生什么。您认为这意味着从现在开始,t0t1是同义词 - 无论何时使用一个,另一个都会受到影响。但实际上,t0t1只是对同一对象的两个引用。

t0进行新的分配只是将其与" blue"分开。反对并重新附加到"紫罗兰"对象

只要t0t1都指向同一个对象,您在其指向对象的内容中所做的任何更改(例如t0.i = 5)都会被其他参考,因为它们都指向同一个对象。但是,只要您将其他内容分配给t0,就会失去与t1的连接。在你这样做之后,改变它将反映在t2,它指向相同的,"紫罗兰"对象,而不是t1仍然指向旧的,"蓝色"之一。

所以:

  • 如果为引用分配一个新值 - 它不再指向与之前相同的对象,并且之前的任何"双引用"失去了。
  • 如果为引用的内容分配新值,它将反映在查看同一对象的所有引用变量中。

This is an illustration of your program

答案 1 :(得分:1)

您在此处不明白的是,在执行t0 = t2时,您将t0的地址引用替换为t1的地址与t2相同的引用t1所以不,它不会影响t0.i

但是,Test t1 = new Test(); t1.i = 1; Test t0 = t1; t0.i = 3; System.out.println(t1.i); //prints 3 会打印2。

但要回答你的问题

  

从其他地方拿到t1对象后有没有办法改变它   通过简单的分配而不直接访问t1? (即t1 = t0)

是的,有办法,请查看此代码段

t1.i

这会将3修改为t0.i访问t2

如果您想使用i对象执行此操作,则可以直接修改Test t1 = new Test(); t1.i = 1; Test t0 = t1; Test t2 = new Test(); t2.i = 2; t0.i = t2.i; System.out.println(t1.i); //prints 2 的值:

{{1}}

答案 2 :(得分:1)

Test t1 = new Test();
t1.i = 1

可以表示为

            +-------+
            | Test  |
t1 -------> +-------+
            | i (1) |
            +-------+

现在当你做

Test t0 = t1;

您从t0分配t1相同值的值,这意味着现在它们保持相同的值(地址到同一个Test实例),所以您的情况是

            +-------+
t1 ----+    | Test  |
       +--> +-------+
t0 ----+    | i (1) |
            +-------+

现在这段代码之后

Test t2 = new Test();
t2.i = 2;

你会有

            +-------+
t1 ----+    | Test  |
       +--> +-------+
t0 ----+    | i (1) |
            +-------+

            +-------+
            | Test  |
t2 -------> +-------+
            | i (2) |
            +-------+

当你做

t0 = t2; 

你将你的情况改为

            +-------+
t1 ----+    | Test  |
       +--> +-------+
            | i (1) |
t0 ----+    +-------+
       |
       |    +-------+
       |    | Test  |
t2 ----+--> +-------+
            | i (2) |
            +-------+

所以你现在看到t0拥有与t2引用所持有的对象相同的对象,但t1引用未被更改,这就是为什么

System.out.println(t1.i)

打印1