33

私は試験があるので勉強していて、ほとんどの Java には問題がありませんが、説明できないルールに出くわしました。コードの一部を次に示します。

public class A {

    public int method(Object o) {
        return 1;
    }

    public int method(A a) {
        return 2;
    }
}

public class AX extends A {

    public int method(A a) {
        return 3;
    }

    public int method(AX ax) {
        return 4;
    }
}

public static void main(String[] args) {
    Object o = new A();
    A a1 = new A();
    A a2 = new AX();
    AX ax = new AX();

    System.out.println(a1.method(o));
    System.out.println(a2.method(a1));
    System.out.println(a2.method(o));
    System.out.println(a2.method(ax));
}

これは以下を返します:

1 3 1 3

私はそれが戻ることを期待していますが:

1 3 1 4

a2 の型によって AX で呼び出されるメソッドが決まるのはなぜですか?

私はルールと継承のオーバーロードについて読んできましたが、これは十分に曖昧なようで、正確なルールを見つけることができませんでした。どんな助けでも大歓迎です。

4

3 に答える 3

32

これらのメソッド呼び出しの動作は、Java 言語仕様(セクション 8.4.9 を参照) によって指示および記述されています。

メソッドが呼び出されると (§15.12)、呼び出されるメソッドのシグネチャを決定するために、コンパイル時に実際の引数 (および明示的な型引数) の数とコンパイル時の引数の型が使用されます ( §15.12.2)。呼び出されるメソッドがインスタンス メソッドである場合、呼び出される実際のメソッドは、動的メソッド ルックアップ (§15.12.4) を使用して、実行時に決定されます。

あなたの例では、Java コンパイラは、メソッドを呼び出しているインスタンスのコンパイル タイプに最も近いものを判断します。この場合:

A.method(AX)

最も近いメソッドはタイプ A のものであり、署名がありますA.method(A)実行時に、A の実際の型 (AX のインスタンス) に対して動的ディスパッチが実行されるため、実際に呼び出されるメソッドは次のようになります。

AX.method(A)
于 2012-06-19T23:18:59.663 に答える
4

もっと簡単に説明します。ここのように、スーパークラス参照でサブクラスオブジェクトを作成したときを参照してください。

スーパークラス参照を使用して呼び出す場合、オブジェクトがサブクラスであってもスーパークラスに移動することに注意してください。この名前のメソッドと適切な署名があるかどうかを確認してください。

それが見つかったら、オーバーライドされているかどうかを確認しますか?? はいの場合、ここのようにサブクラスメソッドに移動します。別の方法では、同じスーパー クラス メソッドを実行します。

私はあなたにその例をあげることができます...ただ隠してください

public int method(A a) {
        return 3;
    }

method & check your answer 1 2 1 2 が得られます。参照を最優先するためです。あなたがそれを呼び出すよりもオーバーライドしたため、3..!!が与えられます。大きくても理解しやすいことを願っています。ハッピーラーニング

于 2014-04-15T08:07:10.157 に答える
1

a2 は A として参照され、JVM は最初に参照を使用します (期待どおりの実際のオブジェクトではありません)。

于 2012-06-19T23:19:40.557 に答える