在这种情况下,JVM如何处理动态调度?

时间:2013-05-28 04:28:57

标签: java jvm polymorphism override dispatch

鉴于以下来源和输出:

来源:

public class A
{
  public void foo()
  {
    bar();
  }

  public void bar()
  {
    System.out.println ("in A's bar() method");
  }
}

public class B extends A
{
  @Override
  public void foo()
  {
    super.foo();

    // Do some specialized B stuff
  }

  @Override
  public void bar()
  {
    System.out.println ("in B's bar() method");
  }
}

public class Main
{
  public static void main (String... args)
  {
    B b = new B();

    b.foo();
  }
}

输出:

in B's bar() method

有人可以向我解释一下JVM在这种情况下如何足够聪明地多态调用B(而不是A的)bar()方法吗?我想知道这里幕后发生了什么样的动态调度魔法。

更新:如果我不够清楚,我基本上知道发生了什么,我正在寻找有关JVM如何在幕后实现的具体细节。到目前为止,答案太简单了。

更新2 :也许我不够清楚。调用b.foo()后,调用super.foo(),然后在A类bar()中调用foo()。在专门调用bar()时调用的super.foo()如何不调用类A的bar()方法,因为super关键字明确指定了类A? JVM需要采取哪些步骤来解决这个问题?

另外,这是否意味着从一般情况下调用公共方法是一个坏主意,因为它们可以通过这种方式被覆盖?

3 个答案:

答案 0 :(得分:3)

Java在调用方法时使用对象的类型。

A b = new B();
b.foo();

假设你使用了上面的代码。 在这里,您将创建一个B类型的对象,并将其分配给类型为A的引用。由于对象类型为B,您将调用B类中的方法。

答案 1 :(得分:1)

即使您当前所在的构造函数或方法是在超类中定义的,该对象也不会更改类型。它仍然是B类型的对象。这可以通过使用this关键字来证明。

this指的是当前对象。这与定义当前方法或构造函数的类不同。

尝试在A的构造函数或foo()方法中输入以下内容:

System.out.println(this.getClass());

答案 2 :(得分:1)

函数调用序列是(来自eclipse调试视图):

1. B.foo()      // super.foo()
2. B(A).foo()   // bar()
3. B.bar()

在线程调用super.foo()之后,JVM将检查B中是否有任何实现(因为我们仍然在堆栈中保存B.class),如果存在,JVM将调用它。

JVM实现保证了此功能。它不是智能,它只是以这种方式设计,就像C ++的虚拟方法一样。

希望它有所帮助。