【问题标题】:Why runtime binding does not happen at compile time?为什么运行时绑定不会在编译时发生?
【发布时间】: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 最终会引用什么类型。它可能是DogCat 甚至Cow(可能已在其他一些库中声明)。简而言之:编译器不一定对最终执行的程序有一个完整的视图。它只看到一个小子集,必须采取相应的行动。
  • “怎么不是运行时绑定”是什么意思?同样,您认为哪种行为会更好?这个问题IMO真的不清楚。
  • @SaurabhDhage:这只是规则。由于不能在所有情况下都这样做,所以它永远不会这样做。这样做有时会不必要地使编译器和运行时复杂化(因为它们现在都需要能够处理两种情况)。请注意,privatestatic 方法实际上在编译期间完全“锁定”了,因此在这些情况下不需要动态查找(因为语言规则保证只有一个可能的候选者)。
  • 只想添加除 privatestatic 之外的 final 方法不是多态的(它们没有动态绑定,因为编译器知道那些不能被覆盖,因此它们不能在子类中有替代主体)。

标签: java


【解决方案1】:

运行时绑定发生在运行时,因为编译器无法决定在编译时执行哪个函数...

这是不正确的,至少在 Java 中是这样。

Java 中的运行时绑定不是 Java 编译器的缺陷造成的。这是设计

Java 中的运行时绑定有很多优点:

  • 这意味着当您对代码库进行更改时,您不必同时编译和链接所有代码。这使得开发速度更快。

  • 这意味着您不必针对特定版本的 Java 运行时进行编译和链接。简而言之,它实现了“一次编写,到处运行”1.

  • 这意味着您的应用程序可以使用第三方提供的插件。

  • 确实,应用程序可以可以加载不同版本的东西来处理平台差异等等。

好消息是 Java 在保持运行时类型安全的同时做到了这一点。


...但是为什么编译器不能在编译时决定?

嗯,他们可以设计了 Java,以便编译器(或链接器)可以在编译时绑定所有内容。但如果他们这样做了,Java 将是一种非常不同的语言。

但鉴于他们以他们的方式设计 Java,实际上不可能在编译时确定某些事情,似乎对读者来说是显而易见的2。这个明显的缺点通常是因为读者没有考虑到以下问题:

  • 新类被添加到类型层次结构中,或者
  • 现有类被修改为具有不同的行为,并单独重新编译。

Joachim 的评论举了一个很好的例子:

“想象一下,初始化不是Animal a = new Dog(),而是Animal a = SomeClassFromALibrary.getAnAnimalBasedOnSomeConfiguration()。现在编译器无法知道a 最终会引用什么类型。它可能是Dog 或@987654324 @ 甚至Cow(可能已在其他库中声明)。简而言之:编译器不一定对最终执行的程序有完整的视图。它只看到一个小子集,必须采取相应的行动。”


1 - 这就是......在某种程度上,“编写一次,到处运行”是现实而不是营销炒作。
2 - 据我所知,您的示例并未说明这一点。

【讨论】:

    猜你喜欢
    • 2010-11-14
    • 2013-04-25
    • 2015-12-02
    • 2015-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-27
    相关资源
    最近更新 更多