关于向上转换和重载方法的困惑



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

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. 现在,查看并执行了更具体的类Subpublic void f(double d)的方法

这是对的吗?

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

因此,在编译时,只有double版本可见,但它将在运行时调度到子类的重写版本。

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

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

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

相关内容

  • 没有找到相关文章

最新更新