0

假设我们有这两个类和一个主要方法:

public class Super {
    public void f(double d){
        System.out.println("Super: f(double d)");
    }
    public void f(int i){
        System.out.println("Super: f(int i)");
    }
}

public class Sub extends Super {
    public void f(double d){
        System.out.println("Sub: f(double d)");
    }

    public void f(float f){
        System.out.println("Sub: f(float f)");
    }
}

public class M {
    public static void main(String[] args){
        Sub a = new Sub();
        a.f(1.5f); //output: "Sub: f(float f)"

        Super b = new Sub();
        b.f(1.5f); //output: "Sub: f(double d)"
    }
}

为什么第二次调用的结果Sub: f(double d)Sub: f(float f)第一次不同?

当我添加

public void f(float f) {
    System.out.println("Super: f(float f)");
}

Super班级,输出变为Sub: f(float f)

鉴于这种行为,我希望工作流程如下所示:

  1. 如上a图所示,检查Super该类Super是否有匹配的方法
  2. public void f(double d)找到,因此将浮点数转换为双精度
  3. 现在可以看到并执行public void f(double d)更具体的类中的方法Sub

这个对吗?

4

2 回答 2

2

要理解此行为,请注意始终在编译时执行从一系列重载方法中选择调用哪个方法。但是,方法分派是在运行时执行的。

因此,在编译时,只有double版本是可见的,但它会在运行时被分派到子类的覆盖版本。

于 2014-12-06T21:02:22.643 回答
1

b.f(1.5f)在编译时查找该方法。它的实现将是运行时更具体的(如果存在),但选择哪个重载方法在编译时绑定。

由于b至少是Super编译器可以推断的唯一结论是该方法将是void f(double v)(因为Super没有float重载),因此选择了一个。

然后在运行时实现是Sub类之一,这要归功于动态绑定。

于 2014-12-06T21:03:37.717 回答