3

Suppose we have the following code snippet:

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

ArrayList<Animal> animalList = new ArrayList<>();
animalList.add(cat);
  1. cat is a reference of type Cat that points to an object of type Cat

  2. animalList.get(0) is a reference of type Animal that points to the same object as the cat reference.

  3. cat == animalList.get(0) will evaluate to true since they are both pointing to the same object.

However, one reference is of type Cat and the other of type Animal(position 0 in list), so am I wrong in saying that the references are not entirely equal, even though they point to the same memory location? Am I looking into the terminology too much?

Bartek Spitza
  • 305
  • 2
  • 15
  • It is the same object. But if cat had a method miaow() that animal doesn't have, I think the compiler would not allow you to write animalList.get(0).miaow() as at compiletime it doesn't know that there is a cat in that place – elPolloLoco Oct 10 '18 at 13:58
  • Using `==` on objects is a memory reference comparison, and indeed they are both pointing to the same memory location. See also: overriding `equals()` and `hashCode()` methods. – Andrew S Oct 10 '18 at 13:59

4 Answers4

5

This existing answer uses a nice analogy around houses, which describes references as "addresses", that allow you to find "houses" (those represent the instantiated objects).

If you extend that thinking, you could say that it's possible to print addresses on different cards. So these cards look different, but the address printed on them is always the same.

So yes, the compiler has a certain understanding of the references (or to be precise: **variables) being "different" (you can't invoke the Cat methods on an Animal reference). But at runtime, that part is completely gone. Then we are only comparing the "address" printed on the "cards".

GhostCat
  • 137,827
  • 25
  • 176
  • 248
  • 1
    Thanks! The last paragraph was really why I was confused, and the compile time and run time explanation makes sense :)) – Bartek Spitza Oct 10 '18 at 14:10
  • "the compiler has a certain understanding of the references being "different"" I wouldn't word it that way. The compiler knows that the *variables* are different. – Michael Oct 10 '18 at 14:10
3

am I wrong in saying that the references are not entirely equal, even though they point to the same memory location?

Yes, you're wrong. A reference is effectively just a memory location.

It seems like you're considering the type of the variable to be part of the reference and it isn't.

Michael
  • 41,989
  • 11
  • 82
  • 128
1

It's a magic of Polymorphism (dynamic polymorphism).

The actual object is determined at runtime and not compile time.

So actually cat and animal is the same (cat) and reference to the same memory.

Please view more detail in this article

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

It explained very well.

Huy Nguyen
  • 1,931
  • 1
  • 11
  • 11
1

so am I wrong in saying that the references are not entirely equal, even though they point to the same memory location?

Yes. They are the same piece of memory/instance, so nothing changes in your memory (it remains at the same memory location). There is no difference or any loss of information when you treat a Cat as an Animal in your code. However, you will only be able to get the Animal's properties since you choose to treat the object as an Animal. If you want to get the Cat's specifics as well, you can just cast the object. This entire process happens only in the preprocessing of the code compilation.

More about casting and this way of working can be seen here: How does Java Object casting work behind the scene?

gi097
  • 7,313
  • 3
  • 27
  • 49