3

次のソースと出力があるとします。

ソース:

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 が (A ではなく) B の bar() メソッドをポリモーフィックに呼び出すほどスマートである理由を説明してもらえますか? ここで舞台裏でどのような動的ディスパッチ マジックが行われているのか知りたいです。

更新:私が十分に明確でない場合、私は基本的に何が起こっているかを知っています.JVMがフードの下でそれをどのように実現するかについての特定の詳細を探しています. これまでの答えは単純すぎます。

更新 2 : たぶん、私は十分に明確ではありませんでした。がb.foo()呼び出されると、次にsuper.foo()が呼び出され、次にbar()がクラス A で呼び出されfoo()ます。キーワードがクラス A を明示的に指定しているため、クラス A のメソッドを呼び出さないでbar()具体的に呼び出したときに呼び出される はどのように行われるのでしょうか? これを解決するために JVM はどのような手順を実行する必要がありますか?super.foo()bar()super

また、これは、この方法でオーバーライドできるため、パブリックメソッドを独自のクラス内から呼び出すのは一般的に悪い考えであることを意味しますか?

4

3 に答える 3

1

関数呼び出しシーケンスは次のとおりです (Eclipse デバッグ ビューから)。

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

スレッドが super.foo() を呼び出した後、JVM は B に実装があるかどうかを確認します (まだ B.class をスタックに保持しているため)、ある場合は JVM がそれを呼び出します。

この機能は、JVM 実装によって保証されています。これはsmartではありません。C++ の仮想メソッドと同じように、このように設計されているだけです。

それが役に立てば幸い。

于 2013-05-30T06:24:28.933 に答える