gpt4 book ai didi

java - 编译时链接和运行时链接有什么区别?

转载 作者:行者123 更新时间:2023-11-30 08:41:56 24 4
gpt4 key购买 nike

我目前正在阅读一本书并卡在以下代码中:

public class TestAnimals {
public static void main (String [] args ) {
Animal a = new Animal();
Animal b = new Horse();

a.eat(); // Runs the Animal version of eat()
b.eat(); // Runs the Horse version of eat()

}
}

class Animal {
public void eat() {
System.out.println("Generic animal eating generically");
}
}

class Horse extends Animal {
public void eat() {
System.out.println("Horse eating hay, oats, horse treats");
}

public void buck() {
}
}

请查看注释行。

这本书接着说“重申一下,编译器只看引用类型,不看实例类型”。真的吗?如果是这种情况,a.eat()b.eat() 都会产生相同的结果,因为它们 (ab) 具有相同的引用类型(即 Animal)。

另外对我来说这似乎是编译时绑定(bind),因为没有使用 virtual 关键字,但在书中结果是运行时绑定(bind)。在这一点上我很困惑。任何帮助将不胜感激。

最佳答案

编译器确实只查看已知的静态类型,而不是实例的实际运行时类型——毕竟,Java 是一种静态类型语言。事实上,除了最微不足道的情况,编译器甚至不知道对象引用的运行时类型(一般情况下要解决这个问题,它必须解决 undecidable problems )。

本书试图说明的重点是这段代码将无法编译:

b.buck();

因为 b 是(编译时)类型 AnimalAnimal 没有 buck()方法。换句话说,Java(如 C++)将在编译时根据它所拥有的有关变量类型的信息验证方法调用是否有意义。

现在本书的结果与运行时绑定(bind)相对应的原因恰恰是因为您在该调用点具有运行时绑定(bind):在 Java 中(与 C++ 不同),所有非静态方法默认都是虚拟的

因此,不需要 virtual 关键字来允许您显式选择加入多态性语义(例如在 C++ 和 C# 中)。相反,您只能通过将它们单独标记为 final 或将它们的包含类标记为 final (如果后者适用于您的情况)来防止对您的方法的任何进一步覆盖。

关于java - 编译时链接和运行时链接有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34773333/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com