假设我们有以下代码段:
Cat cat = new Cat(); // The Cat class extends Animal
ArrayList<Animal> animalList = new ArrayList<>();
animalList.add(cat);
cat
是类型Cat
的引用,指向类型为Cat
的对象
animalList.get(0)
是类型Animal
的引用,它与cat引用指向相同的对象。
cat == animalList.get(0)
将计算为true
,因为它们都指向同一个对象。
但是,一个引用的类型为Cat
,而另一个引用的类型为Animal
(列表中的位置0),所以我错误地指出引用即使指向也并不完全相等到相同的内存位置?我是否过多地研究术语?
答案 0 :(得分:5)
现有的answer在房屋周围使用了一个很好的类比,将引用描述为“地址”,使您可以找到“房屋”(代表实例对象的房屋)。
如果您扩展这种想法,可以说可以在不同卡上打印地址。因此,这些卡外观不同,但它们上打印的地址始终相同。
是的,编译器对引用(或更确切地说是**变量)具有“不同”的理解(您不能在{{1上调用Cat方法}}参考)。但是在运行时,该部分已完全消失。然后,我们只比较印在“卡片”上的“地址”。
答案 1 :(得分:3)
我说引用不是完全相等是错误的,即使它们指向相同的内存位置?
是的,你错了。引用实际上是只是一个内存位置。
似乎您正在考虑将变量的类型作为引用的一部分,但实际上不是。
答案 2 :(得分:1)
这是多态(动态多态)的魔力。
实际对象是在运行时确定的,而不是在编译时确定的。
所以实际上猫和动物是相同的(猫),并且引用相同的内存。
请在本文中查看更多详细信息
http://ocpj8.javastudyguide.com/ch02.html
解释得很好。
答案 3 :(得分:1)
所以我说引用不完全相等是错误的,即使它们指向相同的内存位置?
是的。它们是同一段内存/实例,因此您的内存中没有任何变化(它保持在相同的内存位置)。将Cat
视为代码中的Animal
时,没有任何区别或信息丢失。但是,由于您选择将对象视为Animal
,因此您只能获得Animal
的属性。如果您还想获得Cat
的详细信息,则只需投射对象即可。这整个过程仅在代码编译的预处理中发生。
有关铸造和这种工作方式的更多信息,请参见:How does Java Object casting work behind the scene?