【发布时间】:2021-10-03 07:49:20
【问题描述】:
Runtime binding 发生在运行时,因为编译器无法决定在compile time 处执行哪个函数,但为什么编译器无法在编译时决定?
class Animal{
void eat(){ System.out.println("animal is eating..."); }
}
class Dog extends Animal{
@Override
void eat(){ System.out.println("dog is eating..."); }
}
class Cat extends Animal{
@Override
void eat(){ System.out.println("cat is eating..."); }
}
class Example {
public static void main(String args[]){
Animal a = new Dog();
a.eat();
Animal b = new Cat();
b.eat();
}
}
输出:
dog is eating...
cat is eating...
这些问题没有回答我的问题
【问题讨论】:
-
"...因为编译器无法决定在编译时执行哪个函数" 更准确地说,编译器知道需要执行的方法的 签名,但它不知道还不知道应该从哪里获取该方法的 code (body),因为该决定取决于 runtime 变量所持有的 value 类型所以body需要动态绑定。对于像
void someMethod(SomeInterface val){ val.methodFromInterface(); }这样的代码更容易理解这种逻辑,我们的编译器不知道什么类型的对象将作为参数传递给someMethod。 -
想象一下,初始化是
Animal a = SomeClassFromALibrary.getAnAnimalBasedOnSomeConfiguration(),而不是Animal a = new Dog()。现在编译器无法知道a最终会引用什么类型。它可能是Dog或Cat甚至Cow(可能已在其他一些库中声明)。简而言之:编译器不一定对最终执行的程序有一个完整的视图。它只看到一个小子集,必须采取相应的行动。 -
“怎么不是运行时绑定”是什么意思?同样,您认为哪种行为会更好?这个问题IMO真的不清楚。
-
@SaurabhDhage:这只是规则。由于不能在所有情况下都这样做,所以它永远不会这样做。这样做有时会不必要地使编译器和运行时复杂化(因为它们现在都需要能够处理两种情况)。请注意,
private和static方法实际上在编译期间完全“锁定”了,因此在这些情况下不需要动态查找(因为语言规则保证只有一个可能的候选者)。 -
只想添加除
private和static之外的final方法不是多态的(它们没有动态绑定,因为编译器知道那些不能被覆盖,因此它们不能在子类中有替代主体)。
标签: java