为什么动态调度的目标不是在编译时确定的?

时间:2014-09-08 15:43:58

标签: java inheritance polymorphism superclass method-dispatch

我现在正在阅读一本Java书,并且已经停留了很长一段时间,现在正在思考Dynamic Method Dispatch的工作原理。我知道它是一个强大而有价值的功能,但我不了解它的主要原则。例如,我有一个继承自A类的B类,并覆盖了A的一些方法。所以,当我编写程序时,我可以使用这些表达式

A a = new B();
a.someOverridenMethod();

我知道在这种情况下会调用方法的版本B,而不是A.但是我不理解的部分是,为什么编译器无法确定哪个版本(超类或某些子类) )方法调用?我的意思是,它明确声明变量a将保存对类型B的对象的引用。那么为什么只有在运行时才能确定它,即使它在码?

2 个答案:

答案 0 :(得分:4)

更明确的例子可能是:

A a = null;

if (getUserInput() == 'B')
{
  a = new B();
}
else
{
  a = new C();
}

a.overridenMethod();

编译器可以可能知道将要调用哪个方法 - 用户在运行时确定它!

答案 1 :(得分:1)

你完全误解了运行时的事情。

这意味着class A可以保存将在运行时确定的任何子类的引用。他们可能会在a =new C();之后发表A a = new B();之类的其他陈述,因为它们可以是这样的许多陈述,因此它说该方法的版本将在运行时确定

即。 a将保留B的引用,并且可能在其他时刻它将保留C的引用,其中BC是子类别A

以下是一个例子:

 class A {

void override()
{
    System.out.println("Inside A");
}

}

 class B extends A
{
     void override()
     {
        System.out.println("Inside B");
     }  

}

 class C extends A
 {
     void override()
     {
         System.out.println("Inside C");
     }
 }

 class Main
 {
     public static void main(String args[])
     {
         A a =new A();

         a.override();
         a=new B();

         a.override();

         a=new C();

         a.override();
     }
 }

<强>输出:

Inside A
Inside B
Inside C

希望这可以解除你的怀疑。