2

I have a class Animal which has one child Dog.

class Animal {
    public void makeSound() {
        System.out.println("Animal sound");
    }
}

class Dog extends Animal {
    @Override
    public void makeSound() {
        super.makeSound();
    }
}

public static void main(String[] args) {
    Dog dog = (Dog) new Animal(); // It compiles, but throws runtime exception.
    dog.makeSound();
}

Here if we will cast child to parent, it will compile, but it will throw runtime exception - ClassCastException. Of course, there can be a case when the child will have a field or method which the parent doesn't. That's why we can't cast Dog to Animal. Also, there's no IS-A relationship. But why the cast is not possible, in case parent and child classes have only the same fields and methods?
I've got asked this question in the interview)

Thank you.

  • 1
    What is your actual question? – Bohemian Mar 24 '22 at 18:33
  • Why downcasting is not possible in case parent and child are structurally the same? – User_214534 Mar 24 '22 at 18:35
  • 3
    The terms you are looking for here are [structural type systems](https://en.wikipedia.org/wiki/Structural_type_system) and [nominal type systems](https://en.wikipedia.org/wiki/Nominal_type_system). It is not possible to cast `Animal` to `Dog` simply because Java's type system is designed to be nominal. – Sweeper Mar 24 '22 at 18:51
  • Sorry, I've edited my question – User_214534 Mar 24 '22 at 18:54
  • 1
    You can cast explicitly (`Animal a = new Animal(); Dog dog = (Dog) a`) which will throw a runtime error if `a` is not in fact a dog, see https://www.geeksforgeeks.org/upcasting-vs-downcasting-in-java/ but the compiler won't automatically cast it for you – Esther Mar 24 '22 at 18:54
  • Yeah, this will throw classcastexception – User_214534 Mar 24 '22 at 18:56
  • 3
    https://stackoverflow.com/questions/380813/downcasting-in-java – Esther Mar 24 '22 at 18:58
  • The cast from Animal would work if the reference was concretely of type Dog, e.g. `Animal a = new Dog(); Dog d = (Dog) a;`. – Andy Turner Mar 24 '22 at 19:10
  • Java will only allow objects that are in fact dogs (are instances of `Dog` or a subclass of `Dog`) to be cast to `Dog`. Which fields the class has (or hasn’t) is not taken into consideration. It reflects real life: in reality you cannot make an animal into a dog no matter how similar it is to a dog. – Ole V.V. Mar 24 '22 at 19:29
  • Actually, there are 3 checks. The first 2 checks performs the compiler and the last check JVM. When we write like this `Dog d = (Dog) new Animal()` it passes the first 2 checks of the compiler, but in the runtime, JVM recognizes that this cast is impossible, so in the 3rd check we get classcastexception. – User_214534 Mar 24 '22 at 21:24

1 Answers1

1

When the compiler sees that you are trying to cast the Animal object into a Dog, it "knows" that Dog is underneath Animal in the hierarchy, so it is possible that the animal is a dog, so it allows it. However, at runtime, it turns out that it is just an Animal, and is not a Dog, so the cast fails.

This is a weird case in which it is obvious in reading the program that the Animal is just an Animal and not a Dog because it was just created with "new Animal()", but the compiler doesn't know that--it just knows that it is an Animal. Compilers are smart, but they can't know everything. I hope that makes sense.

ferzle
  • 85
  • 1
  • 11
  • You're right. I answered this question like this, that it's not correct technically because Animal is not a dog, the dog is animal and child class can have other methods/fields, which animal doesn't, but they were not satisfied with this answer)) And after that, they modified the question like assume both child and parent has the same fields/methods... Thank you – User_214534 Mar 24 '22 at 21:27