简体   繁体   English

Java 中的上调/下调

[英]Upcasting/Downcasting in Java

I am trying to understand upcasting and downcasting in Java and I am confused by the following scenario (about my code, which is below):我试图了解 Java 中的向上转换和向下转换,我对以下情况感到困惑(关于我的代码,如下所示):

First - why is it that the code does not compile when I include the line myAnimal.bark();首先 - 为什么当我包含行myAnimal.bark(); , ,

and Second - (assuming I comment out myAnimal.bark(); ) why does calling myAnimal.move() print "moveDog" instead of "moveAnimal" ?第二 - (假设我注释掉myAnimal.bark(); )为什么调用 myAnimal.move myAnimal.move()打印"moveDog"而不是"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 ? myAnimal是否仅限于Animal class 的方法,因为我们已将其类型声明为Animal ,即使我们将其设置为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");
        }
    }


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.第一个概念是static typing ,这意味着 Java 编译器会在编译时检查您的表达式、变量和方法的类型,然后才能运行代码。 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.在这种情况下,变量myAnimal的类型是Animal ,而Animal类型没有方法bark() ,所以myAnimal.bark()是一个类型错误。

The second concept is dynamic dispatch , which means that the method implementation is selected based on the type of the object at runtime .第二个概念是动态分派,即在运行时根据object的类型来选择方法实现。 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.由于myAnimal持有对 class Dog的 object 的引用,因此对move()方法的调用会调用Dog class 中提供的该方法的实现。

With the implicit upcast at this line:使用此行的隐式向上转换:

Animal myAnimal = myDog;

You are not doing anything to change the underlying instance myDog .您没有做任何事情来更改底层实例myDog What you are doing is assigning it to a variable of a type one level higher in the inheritance tree.您正在做的是将其分配给 inheritance 树中更高一级类型的变量。 Effectively, this restricts which methods can be called to only those defined in Animal , but does not change how those methods resolve.实际上,这将哪些方法限制为只能调用Animal中定义的方法,但不会改变这些方法的解析方式。

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.因为您已将可用方法限制为仅在父 class Animal上定义的方法,所以编译器无法解析Dog#bark() ,因为它是Dog的方法,并且变量myAnimal被定义为没有#barkAnimal类型#bark法。

#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. #move()AnimalDog的方法,因此它解析,但它解析为Dog上定义的方法,因为myAnimal仍然引用Dog的实例,尽管被向上转换。

Here you declared the myAnimal as Animal and every animal can't bark.在这里,您将 myAnimal 声明为 Animal 并且每只动物都不能吠叫。 ie myAnimal is referring to Animal here.即 myAnimal 在这里指的是动物。

Animal myAnimal = myDog;动物 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.但可以肯定的是,Dog 是一种可以吠叫的动物,因此您需要通过让 JVM 知道它的类型是 Dog 而不是 Just Animal 来明确地投射您的 myAnimal。

So if you change //myAnimal.bark();所以如果你改变 //myAnimal.bark(); to below it will work!低于它会工作!

((Dog) myAnimal).bark(); ((狗) myAnimal).bark();

Here we casted myAnimal from Animal to Dog.在这里,我们将 myAnimal 从 Animal 转换为 Dog。 hence bark() method is allowed and it does not give any compilation issue.因此 bark() 方法是允许的,它不会产生任何编译问题。

Hope this helps!希望这可以帮助!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM