让我们说,我们有这两个类和一个主要方法:
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)
。
鉴于此行为,我希望工作流程如下所示:
a
升级到Super
时,会检查班级Super
是否有匹配方法public void f(double d)
,因此浮动将转换为双重public void f(double d)
中的方法Sub
这是对的吗?
答案 0 :(得分:2)
要理解这种行为,请注意选择在一系列重载方法中调用哪个方法总是在编译时执行。但是,方法 dispatch 是在运行时执行的。
因此,在编译时,只有double
版本可见,但它将在运行时被调度到子类的重写版本。
答案 1 :(得分:1)
在编译时查找方法b.f(1.5f)
。它的实现将是运行时更具体的(如果存在),但选择了重载方法是在编译时绑定的。
由于b
至少是Super
,编译器可以推断的唯一结论是该方法将为void f(double v)
(因为Super
没有float
重载,以便选择一个。
然后在运行时,由于动态绑定,实现是Sub
类的实现。