2

次のJavaコードがあるとします。

class mainul {

    public static void main(String[] args) {

    /*block 1*/
        B b1 = new B();
        A a1 = b1;
        a1.m1(b1);

    /*block 2*/
        B b2 = new B();
        B a2 = b2;
        b2.m1(a2);
    }
}

class A {

    public static void p(Object o) {
        System.out.println(o.toString());
    }

    public void m1(A a) {
        p("m1(A) in A");

    }
}

class B extends A {

    public void m1(B b) {
        p("m1(B) in B");
    }
}

誰かがこのプログラムの出力がなぜであるかについていくつかの光を当てることができますか

m1(A) in A
m1(B) in B

a1の動的タイプがBであるため、ブロック1の出力は「M1(B)inB」であると予想されます。m1のAとBの関数シグネチャが一致しないことに気付きました(オブジェクトが必要です)。タイプAと他のBの引数)とAのメソッドが優先されるようですが、block2の出力と一致していないように見えるため、これを実際に私の出力にリンクすることはできません。

御時間ありがとうございます

4

4 に答える 4

7

お気づきのように、は異なる引数を取るため、B.m1(B)オーバーライドしませんA.m1(A)(注釈を追加してみて@Overrideください。コンパイラが文句を言うのがわかります)。そのため、への参照を介して呼び出すことはできませんA

ただし、 への参照を介して呼び出すことはできますB

于 2012-04-10T21:16:41.513 に答える
1

コードに従ってください:

ブロック 1

B b1 = new B();   //- variable  b1 (type is B) points to instance of B() 

A a1 = b1;        //- variable  a1 (type is A) points to instance of B() .. same as b1 is
                  // pointing to.

 a1.m1(b1);       // Call Method m1 on a1 (i.e. of class A ) ..IMP catch > as a1 holds
                  // object of b1, if there is method in Class A which is overriden in B,
                  // call that overriden method. But here method m1() is not overriden 
                  // by B  it will call method of class A.

ブロック 2

B b2 = new B();  // variable b2 (type B) points to instance of B()

B a2 = b2;       // variable a2 (type B) points to same instance as b2 is pointing to.

b2.m1(a2);       // call method m1 of b2 (of class B). There is only one method m1 in b2
                 // and b2 holds object of B, it must call method of class B

また、ブロック 1 を "m1(B) in B" にしたい場合は、クラス A のメソッドを仮想としてマークし、クラス B で同じメソッドをオーバーライドします。

于 2012-04-11T03:55:17.753 に答える
1

呼び出されるメソッドは、コンパイル時に設定されます (この場合は A.m1(A))。私はあなたがそれがダイナミックだと思っていることを知っていますよね?動的バインディングはランタイム バインディングです。はい、そうですが、A.m1(A) のメソッドに対してのみ動的です。したがって、 A のサブクラスは代替実装を提供できますが、その署名は同じでなければなりません。そうでない場合、それは同じメソッドではないオーバーロードされたメソッドです。

これは、呼び出しで使用されるパラメーターが動的バインディングで考慮されないことも意味します。メソッド名と正式な署名はコンパイル時に設定されます。タイプを変更すると、同じメソッドではなくなり、呼び出されなくなります。

これを行うと、コンパイラにメソッドを強制的に表示させることができます。

a1.m1( (A)b1 )

これにより、呼び出しようとしているメソッドがコンパイラに通知されます。

于 2012-04-10T21:26:56.100 に答える
0

Oli が言ったように、2 つのメソッド シグネチャは異なります。

ここでそれぞれを呼び出すと:

    B b1 = new B();
    A a1 = b1;
    a1.m1(b1);

    /*block 2*/
    B b2 = new B();
    B a2 = b2;
    b2.m1(a2);

最初にタイプ A のオブジェクトを渡し、次にタイプ B のオブジェクトを渡します。このコンテキストで Java が関心を持っているのはそれだけです。Java は、オブジェクトを何から作成したかは気にせず、それが何であるかだけを気にします。

于 2012-04-10T21:20:33.420 に答える