动态方法绑定异常?

时间:2015-05-07 03:28:07

标签: java polymorphism

一个非常神秘的多态问题:

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);
  }
} 

使用上面的代码,我的输出是&#34; #2 - in Sub.meth(Super)&#34;,而我期待&#34; #3 - in Sub.meth(Sub)&#34;,甚至更奇怪的是,当我发表评论时输出<public void meth(Super other){...}>,输出更改为&#34; #1 - in Super.meth(Super)&#34;。

2 个答案:

答案 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)