【问题标题】:Confusion about upcasting and overloaded methods关于向上转换和重载方法的困惑
【发布时间】:2014-12-06 20:58:49
【问题描述】:

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

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. 现在可以看到并执行更具体的类 Sub 中的方法 public void f(double d)

这对吗?

【问题讨论】:

  • 因为没有方法 f(float) 可通过 Super 类型的引用获得。

标签: java casting overloading upcasting


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-28
      • 1970-01-01
      • 2013-09-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多