3
 class A{
 void m1(A a) {System.out.print("A");}
  } 
  class B extends A{
  void m1(B b) {System.out.print("B");}
  } 
  class C extends B{
  void m1(C c) {System.out.print("C");}
  }

 public class d {

 public static void main(String[] args) {

  A c1 = new C(); C c2 = new C();c1.m1(c2);

 }}

このコードの出力はです'A'

しかし、クラスAを次のように変更すると、次のようになります。

 class A{
 void m1(C a) {System.out.print("A");}
  }

その場合、出力は'C'です。誰かがこのコードがどのように機能しているか説明してもらえますか?

4

1 に答える 1

10

(パラメーターの種類と実装の両方に同じ継承階層を使用することで、これを必要以上に混乱させました。これらを分離すると、おそらく頭の中で単純化するのに役立ちます。)

のタイプはc1ですA。したがって、呼び出すメソッドシグネチャを決定するとき、コンパイラはで宣言されたメソッドのみを確​​認できますA

したがって、最初のケースでは、コンパイラはm1(A);を呼び出します。2番目のケースでは、コンパイラはを呼び出しますm1(C)

最初のケースでは、m1(A)メソッドがオーバーライドされることはないため、実際にはの実行時タイプc1は関係ありません。

2番目のケースでm1(C)は、はによってオーバーライドされます。したがって、の実行時タイプがであるためC、の実装が呼び出されます。Cc1C

覚えておいてください:

  • 過負荷解決(メソッドシグニチャが呼び出される)は、メソッドターゲットと引数式の両方のコンパイル時タイプに基づいて、コンパイル時に決定されます。
  • そのメソッドシグネチャの実装(オーバーライド)は、実行時のターゲットオブジェクトの実際のタイプに基づいています。
于 2012-09-25T16:54:50.047 に答える