【问题标题】:Java changes reference but not the object itself?Java更改引用但不更改对象本身?
【发布时间】:2015-03-30 06:26:02
【问题描述】:

请看以下代码:

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)

【问题讨论】:

  • “在我从其他地方得到 t1 对象后,有没有办法通过简单的赋值而不直接访问 t1 来更改它?”不,您只能使用= 运算符(如reference = otherInstance)重新分配引用,因此如果您想在t1 中包含来自t0 的实例,您唯一的选择是t1 = t0

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


【解决方案1】:

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

但是,t0.i 会打印 2。

但是要回答你的问题

在我从其他地方得到 t1 对象后,有什么方法可以更改它 通过简单的分配而不直接访问 t1? (即 t1 = t0)

是的,有办法,检查这个sn-p

Test t1 = new Test();
t1.i = 1;
Test t0 = t1;
t0.i = 3;
System.out.println(t1.i); //prints 3

这会将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

【讨论】:

  • 但是如果 Test 对象比只保存一个整数要复杂得多,我认为显式分配每个成员是不合理的(例如,假设有一天有人会添加新成员 b到测试类,它不会被复制到 t1)
  • @Niros 我同意你的观点,我只是想展示可能性并解释为什么你的 sn-p 没有返回你所期望的。但是,在您的评论中修复示例的可能性包括将每个对象保留在一个数组中,然后重新分配您可以执行 arrayOfObjectT[3] = newObjectT;
【解决方案2】:
Test t1 = new Test();
t1.i = 1

可以表示为

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

现在当你这样做了

Test t0 = t1;

您分配给t0 的值与来自t1 的值相同,这意味着现在它们拥有相同的值(相同测试实例的地址),所以您的情况是

            +-------+
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

【讨论】:

    【解决方案3】:

    这是您的程序及其功能的说明。系统的每个状态都以虚线分隔。

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

    t0 进行新分配只需将其与“蓝色”对象分离,然后将其重新附加到“紫色”对象。

    只要t0t1 都指向同一个对象,您对其指向的对象(例如t0.i = 5)的内容所做的任何更改都会被另一个引用看到,因为它们都指同一个对象。但是,一旦您将其他内容分配给t0,它就会失去与t1 的连接。完成此操作后,更改将反映在 t2 中,它指向同一个“紫色”对象,而不是 t1,它仍然指向旧的“蓝色”对象。

    所以:

    • 如果您为引用分配一个新值 - 它不再像以前那样指向同一个对象,并且任何以前的“双重引用”都将丢失。
    • 如果您为引用的内容分配一个新值,它将反映在所有查看同一对象的引用变量中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-09-25
      • 2013-01-14
      • 2022-09-21
      • 1970-01-01
      • 2012-04-09
      • 2018-04-09
      • 2013-05-01
      相关资源
      最近更新 更多