java - 对动态绑定(bind)的误解

标签 java inheritance dynamic binding

根据我对动态绑定(bind)的理解,JVM 在运行时查看对象的实际类型并搜索该类中的实现,并通过继承级别向上工作。

例如,如果我们有:Vehicle v = new Car();

假设类Car扩展了Vehicle,我们可以看到引用变量类型为Vehicle,对象类型为Car。

如果我们说:v.start():

JVM 将首先在 Car 类中查找 start 方法实现,然后在 Vehicle 类中查找。

此代码中的一个示例:

public class scratch{
    public static void main(String [] args){
        Vehicle v = new Car(); 
        v.start(); 
    }
}

class Vehicle{
    public void start(){
        System.out.println("Vehicle class"); 
    }
}

class Car extends Vehicle{
    public void start(){
        System.out.println("Car class"); 
    }
}

此代码的输出如预期所示:“Car class”

这是我的问题:如果我从类Vehicle中取出start方法,完全删除它,程序将不再运行。根据我对动态绑定(bind)的理解,JVM 仍然应该查看对象的实际类型(在本例中是 Car),并且仍然运行 start 方法的 car 实现。然而,它并没有这样做。

为什么?

最佳答案

删除 start() 时出现问题来自Vehicle与多态性有关。在 Vehicle ,如果您定义 start()在这里,这就是所有 Vehicle 所说的s,甚至子类,都有这个方法。

如果删除 start()来自Vehicle() ,那么就不能保证任何Vehicle有一个start()方法,即使我们知道它是 Car确实有start() 。如果有HorselessCarriage怎么办?扩展类Vehicle但没有定义start() ?那么,就没有start()了方法。因此,如果没有start()方法Vehicle ,你不能调用start()Vehicle上变量。

能够调用 start() 的全部意义在Vehicle上是为了确保任何 Vehicle实现有 start()调用方法。

更新

JVM 获取对象的运行时类型并查找与方法调用的签名相匹配的方法。如果没有找到,它将沿着继承树向上走到父类(super class)并查找那里的方法。

更多详细信息参见 JLS, Section 15.12.4.4 :

Let X be the compile-time type of the target reference of the method invocation. Then:

If class S contains a declaration for a non-abstract method named m with the same descriptor (same number of parameters, the same parameter types, and the same return type) required by the method invocation as determined at compile time (§15.12.3), then:

If the invocation mode is super or interface, then this is the method to be invoked, and the procedure terminates.

If the invocation mode is virtual, and the declaration in S overrides (§8.4.8.1) X.m, then the method declared in S is the method to be invoked, and the procedure terminates.

If the invocation mode is virtual, and the declaration in S does not override X.m, and moreover X.m is declared abstract, then an AbstractMethodError is thrown.

Otherwise, if S has a superclass, this same lookup procedure is performed recursively using the direct superclass of S in place of S; the method to be invoked is the result of the recursive invocation of this lookup procedure.

在这里,S似乎是对象的运行时类型。

关于java - 对动态绑定(bind)的误解,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19189264/

相关文章:

c++ - C++动态哈希表

java - 使用 Web 服务从数据库检索数据

java - 新手问题: passing objects in java?

java - 在每个页面jsp/servlet进行登录验证

java - 多线程循环赛

c++ - 为什么析构函数被执行了两次?

具有泛型参数基础的 Java 泛型参数

C 双重释放错误

c# - Scala有没有类似于C#的显式接口(interface)实现?

c++ - Qt GUI - 仅当值更改时才想从 .txt 文件中读取