2

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

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

我知道在这种情况下会调用方法的版本 B,而不是 A。但我不明白的部分是,为什么编译器不能确定要调用的方法的版本(超类或某个子类)?我的意思是,它明确指出该变量a将包含对 B 类型对象的引用。那么为什么即使它在代码中明确说明,它也只能在运行时确定呢?

4

2 回答 2

4

一个更清楚的例子可能是:

A a = null;

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

a.overridenMethod();

编译器不可能知道这里将调用哪个方法——它由用户在运行时确定!

于 2014-09-08T17:19:55.637 回答
0

你完全误解了运行时的东西。

这意味着它class A可以保存将在运行时确定的任何子类的引用。他们可能还有其他语句,例如a =new C();afterA a = new B();并且由于它们可以是许多这样的语句,因此据说该方法的版本将在运行时确定

即将a持有参考,B也许在其他时刻它将持有C两者的参考,B并且C是的子类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

希望这可以消除您的疑问。

于 2014-09-08T17:17:08.063 回答