【问题标题】:Difference between object and reference in java with code?java中的对象和引用之间的区别与代码?
【发布时间】:2013-07-12 07:51:29
【问题描述】:
public class TestVO {

    public static void main(String[] args) {
        VO vo1 = new VO();
        VO vo2 = new VO();
        VO vo3;
        VO vo4 = new VO();

        vo1.setName("Sourav");
        vo2.setName("Anil");

        vo3 = vo1;
        vo4 = vo1;

        System.out.println(" " + vo4.getName());

        vo1.setName("Abhishek.");

        System.out.println(vo1.getName() + "  " + vo2.getName() + " " + vo3.getName() + " " + vo4.getName());
    }
}

--输出是:---

Sourav

Abhishek.  Anil Abhishek. Abhishek.

VO 是一个简单的类,包含 String name 并包含 gettersetter

在第一个 System.out.println *vo4.getName()* 打印:Sourav 好的。没关系。

但在第二个 System.out.println *vo4.getName()* 打印:Abhishek.

我的问题是为什么第二次打印是 Abhishek.。我在 vo4 对象中保留了 vo1 对象的副本,而不是参考。这意味着它创造了一个新的记忆。 vo1 和 vo4 是不同的。那么为什么 vo4.getName 在第二次更改。我正在设置 vo1 对象,但 vo4 会自动更改。为什么会这样??

【问题讨论】:

  • 您使用 new 关键字创建对象,= 将该对象的 引用 传递到变量中,同样 var1=var2 复制引用不是对象

标签: java


【解决方案1】:

我在 vo4 对象中保留了 vo1 对象的副本,而不是引用。

不,您已将变量 vo1vo4 指向 same 对象,如下所示:

+-----+
| vo1 |--------\
+-----+ \ +----------------+
                 --->| (对象) |
+-----+ / |姓名 = 阿比舍克 |
| vo4 |--------/ +----------------+
+-----+

让我们按照代码来:

VO vo1 = new VO();

给我们:

+-----+ +----------------+
| vo1 |-------------->| (对象) |
+-----+ |名称 = 空 |
                     +----------------+

然后:

VO vo2 = new VO();

现在我们有了:

+-----+ +----------------+
| vo1 |-------------->| (对象) |
+-----+ |名称 = 空 |
                     +----------------+

+-----+ +----------------+
| vo2 |-------------->| (对象) |
+-----+ |名称 = 空 |
                     +----------------+

然后:

VO vo3;

...它只是用null 创建vo3(不指向任何对象)。

然后:

VO vo4 = new VO();

所以我们有:

+-----+ +----------------+
| vo1 |-------------->| (对象) |
+-----+ |名称 = 空 |
                     +----------------+

+-----+ +----------------+
| vo2 |-------------->| (对象) |
+-----+ |名称 = 空 |
                     +----------------+
+-----+
| vo3 | (一片空白)
+-----+

+-----+ +----------------+
| vo4 |------------->| (对象) |
+-----+ |名称 = 空 |
                     +----------------+

现在:

vo1.setName("Sourav");
vo2.setName("Anil");

给我们:

+-----+ +----------------+
| vo1 |-------------->| (对象) |
+-----+ |姓名 = 苏拉夫 | ***变化就在这里***
                     +----------------+

+-----+ +----------------+
| vo2 |-------------->| (对象) |
+-----+ |姓名 = 阿尼尔 | *** 和这里 ***
                     +----------------+
+-----+
| vo3 | (一片空白)
+-----+

+-----+ +----------------+
| vo4 |------------->| (对象) |
+-----+ |名称 = 空 |
                     +----------------+

这里是有趣的地方:

vo3 = vo1;
vo4 = vo1;

vo3 指向同一个对象vo1 指向,并且还将vo4 指向该对象,释放对象vo4 曾经指向的对象(这变得符合条件用于垃圾收集)。给我们:

+-----+
| vo1 |----\
+-----+ \
             \
+-----+ \ +----------------+
| vo3 |------------->| (对象) |
+-----+ / |姓名 = 苏拉夫 |
             / +----------------+
+-----+ /
| vo4 |----/
+-----+

+-----+ +----------------+
| vo2 |-------------->| (对象) |
+-----+ |姓名 = 阿尼尔 |
                     +----------------+

现在

System.out.println(" " + vo4.getName());

...如您所愿,给了我们“Sourav”。

然后

 vo1.setName("Abhishek.");

...改变vo1vo3vo4都指向的对象:

+-----+
| vo1 |----\
+-----+ \
             \
+-----+ \ +----------------+
| vo3 |------------->| (对象) |
+-----+ / |姓名 = 阿比舍克 |
             / +----------------+
+-----+ /
| vo4 |----/
+-----+

+-----+ +----------------+
| vo2 |-------------->| (对象) |
+-----+ |姓名 = 阿尼尔 |
                     +----------------+

...所以getName() on vo1vo3vo4 会给你“Abishek”。

【讨论】:

  • @GrahamSmith:爱我一些 ASCII 艺术。不过,我可能应该使用yuml.me。 :-)
  • @ABasak:很高兴有帮助!
  • @ABasak:如果上述(或发布的任何其他答案)回答您的问题,Stack Overflow 的工作方式,您将通过单击复选标记“接受”答案在它的旁边。更多:meta.stackexchange.com/questions/5234/…
【解决方案2】:

因为 vo1 和 vo4 都指向同一个对象。

下面的赋值使 vo4 引用一个被 vo1 引用的对象。

vo4 = vo1;

因此,任何引用(无论是 vo1 还是 vo4)对引用对象所做的任何更改都将反映到同一个对象。

因此,如果您更改 vo4.setName("xyz"),它会更改 vo4 引用的对象,但实际上 vo1 也引用同一个对象。因此,在为一个对象分配的一个内存位置进行更改,该对象被许多引用(在本例中为 vo1 和 vo4)引用。

【讨论】:

    【解决方案3】:

    您正在为 vo1vo4 分配相同的对象引用。

    vo4 = vo1;
    

    现在两个引用变量都指向同一个对象。

    【讨论】:

      【解决方案4】:

      对象是一个实体,它将存储其中定义的字段的实际值。对象将使用new关键字在内存上创建,并且引用将返回给引用变量。引用变量不是对象。 因此,在您的示例中,new VO() 将在堆内存上创建对象,VO1 将引用它。

      【讨论】:

        【解决方案5】:

        当您执行vo4 = vo1; 时,您只需通过引用vo4 来复制vo1,换句话说,您执行指针分配,因此它们都分配到内存中的相同位置,如果vo1 更改它也会导致也影响vo4,如您所见

        【讨论】:

          【解决方案6】:

          java 中除了基本数据类型之外的所有东西都是指针。创建vo4 后,您将其设置为等于vo1。现在vo4 指向v01

          【讨论】:

            【解决方案7】:

            vo4 = vo1 表示引用变量vo4 引用了vo1 引用的对象。所以vo1vo4 都会引用同一个对象

            阅读本教程的第一部分。你不需要走到最后,因为它是关于垃圾收集的,但它详细解释了如何将引用分配给对象以及它们是如何改变的。

            http://www.thejavageek.com/2013/06/22/how-do-objects-become-eligible-for-garbage-collection/

            【讨论】:

              【解决方案8】:

              我要准备以下图片: 如您所见,vo1、Vo3、Vo4 指向同一个对象

              【讨论】:

              • 最简单的图来理解。谢谢。
              • @ABasak:除了标签是向后的。变量在栈上,而不是堆上;对象在堆中,而不是堆栈中。
              • @T.J. Crowder:非常感谢您的评论,我纠正了这个错误
              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2011-03-14
              • 1970-01-01
              • 1970-01-01
              • 2012-01-12
              • 2011-06-20
              • 2013-05-19
              • 1970-01-01
              相关资源
              最近更新 更多