一个非常神秘的多态问题:
import static java.lang.System.*
class Super{
public void meth(Super other){
out.println("#1 - in Super.meth(Super)");
}
}
class Sub extends Super{
public void meth(Super other){
out.println("#2 - in Sub.meth(Super)");
}
public void meth(Sub other){
out.println("#3 - in Sub.meth(Sub)");
}
}
public class MethodTest{
public static void main(String[] args){
Super sup = new Super();
Sub sub = new Sub();
Super sup_ref_sub = new Sub();
sup_ref_sub.meth(sub);
}
}
使用上面的代码,我的输出是" #2 - in Sub.meth(Super)
",而我期待" #3 - in Sub.meth(Sub)
&#34;,甚至更奇怪的是,当我发表评论时输出<public void meth(Super other){...}>
,输出更改为&#34; #1 - in Super.meth(Super)
&#34;。
答案 0 :(得分:0)
虽然sup_ref_sub
实际上是Sub
,因为它声明为Super
,但它的行为却是Super
。
Super
只有public void meth(Super)
作为其唯一方法;因此,为什么#2和#3会在你的测试中打印出来。
要打印#3,请将sup_ref_sub
声明为Sub
答案 1 :(得分:0)
你认为实际类型的对象将用于确定要调用的方法是正确的,所以在这种情况下我们有两个选择:
public void meth(Super other)
public void meth(Sub other)
在Java中,动态方法分派仅针对调用方法的对象发生,而不是针对重载方法的参数类型。 现在按照Java doc:
调用方法时(第15.12节),实际参数的数量(和 任何显式类型参数)和的编译时类型 在编译时使用参数来确定签名 将被调用的方法(§15.12.2)。如果方法是 invoked是一个实例方法,要调用的实际方法是 使用动态方法查找(第15.12.4节)在运行时确定。
现在编译类型的类型为Super
,因此调用的方法将为public void meth(Super other)
。这是行的输出:
Super sup_ref_sub = new Sub();
sup_ref_sub.meth(sub);
将是#2 - in Sub.meth(Super)
。