Upcasting/Downcasting in Java

痞子三分冷 提交于 2020-02-14 02:32:30

问题


I am trying to understand upcasting and downcasting in Java and I am confused by the following scenario (about my code, which is below):

First - why is it that the code does not compile when I include the line myAnimal.bark();,

and Second - (assuming I comment out myAnimal.bark();) why does calling myAnimal.move() print "moveDog" instead of "moveAnimal"? Isn't myAnimal restricted to methods from the Animal class because we have declared its type to be Animal, even though we are setting it to a type of Dog?

Any help is greatly appreciated! Here is the code:

    public class Animal {
        public void move() {
            System.out.println("moveAnimal");
        }

       public static void main(String[] args) {
          Dog myDog = new Dog();
          Animal myAnimal = myDog;
          myAnimal.move();
          //myAnimal.bark();
       }
    }

    class Dog extends Animal {
        @Override
        public void move() {
           System.out.println("moveDog");
        }

        public void bark() {
            System.out.println("bark");
        }
    }



回答1:


With the implicit upcast at this line:

Animal myAnimal = myDog;

You are not doing anything to change the underlying instance myDog. What you are doing is assigning it to a variable of a type one level higher in the inheritance tree. Effectively, this restricts which methods can be called to only those defined in Animal, but does not change how those methods resolve.

Because you have restricted the methods available to only those defined on the parent class Animal, the compiler cannot resolve Dog#bark(), since it is a method of Dog, and the variable myAnimal is defined to be of type Animal which has no #bark method.

#move() is a method of both Animal and Dog, so it resolves, but it resolves to the method defined on Dog, since myAnimal still refers to an instance of Dog, despite being upcast.




回答2:


There are two important concepts which are competing with each other here.

The first concept is static typing, which means the Java compiler checks the types of your expressions, variables and methods at compile-time, before the code ever gets a chance to run. In this case, the variable myAnimal is of type Animal, and the type Animal does not have a method bark(), so myAnimal.bark() is a type error.

The second concept is dynamic binding, which means that the method implementation is selected based on the type of the object at runtime. Since myAnimal holds a reference to an object of the class Dog, the call to the move() method invokes the implementation of that method provided in the Dog class.




回答3:


Here you declared the myAnimal as Animal and every animal can't bark! i.e myAnimal is referring to Animal here.

Animal myAnimal = myDog;

But for sure Dog is an animal which can bark, hence you need to explicitly cast your myAnimal by letting JVM know its of type Dog and not Just Animal.

So if you change //myAnimal.bark(); to below it will work!

((Dog) myAnimal).bark();

Here we casted myAnimal from Animal to Dog. hence bark() method is allowed and it does not give any compilation issue.

Hope this helps!



来源:https://stackoverflow.com/questions/58721207/upcasting-downcasting-in-java

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!