静态多态和动态多态之间会发生什么

问题描述 投票:0回答:1

实在找不到正确的答案。 如果我们有:

1.动物猫 = new Cat();

2.动物animal = new Animal();

动物和猫都有方法 makeSound();

1. 据我所知,Java 中的早期绑定发生在编译时,并且方法调用根据引用类型进行绑定。 所以在编译时它决定从 Animal 调用方法。

然后我们有运行时,看起来真实的对象是 Cat 并且那里有一个重写方法,此时发生了延迟出价?

我的问题是java首先进行静态绑定,然后在运行时再次检查实际对象并再次重新绑定?

他们说编译绑定比运行时更快,但看起来即使 Cat 中没有重写方法,运行时绑定也会参与其中?看起来像头顶

  1. 在第二种情况下,Java 检查实际对象没有意义?还是无论如何都会检查?

注解@Override也会以某种方式帮助做出这个决定吗?

我尝试谷歌,但找不到直接的答案,聊天 GPT 把我彻底搞砸了

java jvm javac
1个回答
0
投票

java会首先进行静态绑定,然后在运行时再次检查实际对象并再次重新绑定吗?

是的

但看起来即使 Cat 中没有重写方法,运行时绑定也会参与其中?看起来像头顶

这有点像问为什么人们早上还要吃早餐,而他们无论如何都会在晚上吃晚餐。

静态绑定发生在编译时,动态绑定发生在运行时。它们是完全不同的过程。例如,编译器会进行重载解析(例如,在

foo(int)
foo(String)
之间进行选择),因此 JVM 不必执行此操作。如果有的话,在运行时执行所有操作都会增加运行时开销。

请参阅 JLS 的这一部分,分别了解编译时发生的情况和运行时发生的情况。

此外,进行静态绑定还有一个额外的好处,即您不会意外调用不存在的方法,或者传递了错误的参数。如果编译器成功绑定,这也意味着您调用的方法确实存在并且参数类型也有效。您可以非常确定该方法调用将在运行时成功,并且您没有犯任何拼写错误。

在第二种情况下,Java 检查实际对象没有意义?还是无论如何都会检查?

无论如何它都会检查。它们都编译为

invokevirtual
指令,该指令在运行时执行 方法选择。如果动态调度的开销是一个性能问题,您可能不应该使用 Java。

还要注意,如果调用静态方法,则不存在动态分派。 JVM 将尝试在一个类中查找与指定名称匹配的方法。

注解@Override也会以某种方式帮助做出这个决定吗?

不,

@Override
只是让编译器检查您是否确实重写了超类中的方法,如果没有,请告诉您。另请参阅我的回答

© www.soinside.com 2019 - 2024. All rights reserved.