【问题标题】:Are these references really the same?这些引用真的一样吗?
【发布时间】:2019-03-15 11:03:32
【问题描述】:

假设我们有如下代码sn-p:

Cat cat = new Cat(); // The Cat class extends Animal

ArrayList<Animal> animalList = new ArrayList<>();
animalList.add(cat);
  1. catCat 类型的引用,它指向 Cat 类型的对象

  2. animalList.get(0)Animal 类型的引用,它指向与 cat 引用相同的对象。

  3. cat == animalList.get(0) 将评估为 true,因为它们都指向同一个对象。

但是,一个引用是Cat 类型,另一个是Animal(列表中的位置0),所以我说这些引用不完全相等是错误的,即使它们指向相同的内存地点?我是否过多地研究术语?

【问题讨论】:

  • 是同一个对象。但是如果 cat 有一个动物没有的方法 miaow() ,我认为编译器不会允许你编写 animalList.get(0).miaow() 因为在编译时它不知道里面有一只猫那个地方
  • 在对象上使用== 是内存引用比较,实际上它们都指向同一个内存位置。另请参阅:覆盖 equals()hashCode() 方法。

标签: java


【解决方案1】:

现有的answer 在房屋周围使用了一个很好的类比,它将引用描述为“地址”,允许您找到“房屋”(那些代表实例化的对象)。

如果您扩展这种想法,您可以说可以在不同卡上打印地址。所以这些卡片看起来不同,但印在上面的地址总是一样的。

所以是的,编译器对“不同”的引用(或者准确地说:**变量)有一定的了解(您不能在 Animal 上调用 Cat 方法参考)。但是在运行时,那部分完全消失了。那么我们只是比较“卡片”上打印的“地址”。

【讨论】:

  • 谢谢!最后一段确实是我感到困惑的原因,编译时和运行时的解释很有意义:))
  • "编译器对“不同”的引用有一定的理解"我不会那样说。编译器知道变量是不同的。
【解决方案2】:

我说引用并不完全相等,即使它们指向同一个内存位置,我错了吗?

是的,你错了。引用实际上只是一个内存位置。

您似乎正在考虑将变量的类型作为引用的一部分,但事实并非如此。

【讨论】:

    【解决方案3】:

    这是多态性(动态多态性)的魔法。

    实际对象是在运行时而不是编译时确定的。

    所以实际上猫和动物是相同的(猫)并且引用相同的内存。

    请在本文中查看更多详细信息

    http://ocpj8.javastudyguide.com/ch02.html

    解释得很好。

    【讨论】:

      【解决方案4】:

      我说引用并不完全相等,即使它们指向同一个内存位置,我错了吗?

      是的。它们是同一块内存/实例,因此您的内存中没有任何变化(它保持在相同的内存位置)。当您在代码中将Cat 视为Animal 时,没有任何区别或任何信息丢失。但是,您将只能获得Animal 的属性,因为您选择将对象视为Animal。如果您还想获得Cat 的详细信息,您可以只转换对象。这整个过程只发生在代码编译的预处理中。

      更多关于铸造和这种工作方式的信息可以在这里看到:How does Java Object casting work behind the scene?

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-11-30
        • 2012-03-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-03-01
        • 2014-08-06
        相关资源
        最近更新 更多