超类引用无法在Java中调用子类方法

Nik*_*rma 2 java polymorphism inheritance

我对Java中的多态性有一个基本的疑问.我已将下面的代码写在一个名为AnimalTestDrive.java的文件中.根据我的说法,下面的代码应该特别使用粗体,但不幸的是它不是.你能解释一下原因吗,我已经给出了以下错误:

class Dog extends Animal {

    public void dogMethod() {
        System.out.println("In Dog method");
    }
}

public class AnimalTestDrive {
    public static void main(String args[]) {
        Dog d = new Dog();
        d.dogMethod();
        d.animalMethod();

        Animal animal = new Animal();
        animal.animalMethod();

        animal = d;
        **animal.dogMethod(); // THIS IS NOT WORKING**

    }
}
Run Code Online (Sandbox Code Playgroud)

Jon*_*eet 10

让我们尝试以与编译器相同的方式查看此行:

animal.dogMethod();
Run Code Online (Sandbox Code Playgroud)

首先,它需要弄清楚animal意味着什么.这很好也很简单 - 它是当前方法中的局部变量,所以它不需要看得太远.

该变量的编译时类型是Animal.编译器不关心变量的在执行时是什么 - 它只使用有关声明类型的信息.

所以,这就是它用来试图查找dogMethod()在上下文中的含义animal,即类型Animal.首先它查找Animal,然后在java.lang.Object(隐式超类Animal) - 但这些类都没有包含声明dogMethod.此时,编译器必须放弃错误 - 它无法找到该方法.该方法在引用的值的对象的执行时类型上可用并不重要animal.它必须在编译时使用编译时可用的信息绑定它.

执行时做出的唯一决定是使用哪种方法实现 - 例如,如果您调用animal.toString()并且Dog类具有覆盖,例如

@Override public String toString() {
    return "I'm a dog";
}
Run Code Online (Sandbox Code Playgroud)

那么编译器会发现toString(),从方法java.lang.Object,所以它会知道该方法调用是有效的-但在执行Dog会因为对象的运行时类型的使用.

  • @NikhilSharma什么运行时?这在编译时无法编译. (2认同)