child class 是否在内部调用 parent 方法的 super?

Does child class internally call super of parent method?

我对方法覆盖有一点疑问。

Animal animal = new Dog();
animal.makeSound();

狗是动物的childclass。 animal.makeSound() 会调用 dog object makeSound() 因为它是后期绑定。当我们不覆盖 dog 时,它将调用动物 class makeSound()。但是让我们看看这段代码。

Dog dog = new Dog();
dog.makeSound();

如果狗不覆盖parent方法,它仍然有parent方法,这在继承的情况下是正常的。我只是想知道内部实现。 dog是不是在内部重写了parent方法,在里面像这样调用super?

@Override
public void makeSound() {
    super.makeSound();
}

谢谢。

没有。您可以使用 javap(显示字节码的反编译器工具)来检查这一点。狗class根本就没有makeSound方法

编译器看到字符“dog.makeSound()”并知道 Animal.class 和 Dog.class 是什么样子——因为它们在 class 路径上,或者那些在同一个汇编 运行 中。因此,编译器本身 'resolves' 你的意思。如果缺少 Dog 或 Animal,编译器将出错,告诉您缺少必需的 class,然后收工 - 没有 class 文件,剩下的就没有意义了。

在 class 文件格式中,方法调用 完全规范 。它们的标识基于完全限定的 class 名称 and 方法名称 and 所有参数的确切类型(没有泛型) return类型。只有当所有这些都相同时,JVM 才会认为它是相同的方法。就 JVM 而言,java 代码 "foo".toLowerCase() 中的方法被命名为:“java/lang/String::toLowerCase::()Ljava/lang/String;”。一口,幸运的是,我们在 java 中编程,而不是在字节码中。

因此,在 class 级别,您的 "dog.makeSound();" 被编译为类似以下内容的内容:

INVOKEVIRTUAL com.foo.User214534sPackage.Animal :: makeSound :: ()V

和 JVM,当它看到这个时,检查堆栈顶部的内容(因为这是一个实例方法,'receiver'(dog. 部分)实际上是第一个参数),检查actual 类型是变量指向的对象的类型,计算出它是 com.foo.User214534sPackage.domestics.Dog,并检查所说的 class 是否有 makeSound 方法定义。如果是,JVM 将实际调用它(即使 INVOKEVIRTUAL 调用仅提及 Animal.makeSound)。如果没有,它将检查 Dog 的父类型.. 并将继续这样做,直到它到达 Animal,它当然有一个 makeSound 方法(如果没有,javac 就无法产生class 文件)。