关于上传和重载方法的困惑

时间:2014-12-06 20:58:49

标签: java casting overloading upcasting

让我们说,我们有这两个类和一个主要方法:

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 个答案:

答案 0 :(得分:2)

要理解这种行为,请注意选择在一系列重载方法中调用哪个方法总是在编译时执行。但是,方法 dispatch 是在运行时执行的。

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

答案 1 :(得分:1)

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

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

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