20

アノテーションのJavadocを読ん@Overrideで、次のルールに出会いました。

メソッドにこの注釈型の注釈が付けられている場合、次の条件の少なくとも 1 つが保持されない限り、コンパイラはエラー メッセージを生成する必要があります。

  • メソッドは、スーパータイプで宣言されたメソッドをオーバーライドまたは実装します。
  • このメソッドには、Object で宣言されたパブリック メソッドのシグネチャとオーバーライド等価なシグネチャがあります。

最初の点についてははっきりしていますが、2 番目の点についてはよくわかりません。

「オーバーライド同等」とはどういう意味ですか? この点で、public メソッドはどのようにObject特別なのですか? そして、なぜこれが最初の基準でカバーされないのですか?

さらに、これは Java 7+ ドキュメントにのみ当てはまります。Java 6 docは、オーバーライド等価性について何も述べていません。変更の理由


アップデート:

JLS (セクション 8.4.2 ) をさらに調べた後、オーバーライド等価性の次の説明を見つけました。

メソッドの署名m1は、次のいずれかの場合、メソッドの署名のサブ署名です。m2

  • m2m1、またはと同じ署名を持っています
  • の署名は、 の署名の消去 ( §4.6 )m1と同じです。m2

2 つのメソッド シグネチャm1m2は、 のサブシグネチャであるか、 のサブシグネチャである場合、オーバーライド同等です。m1m2m2m1

私が知る限り、これは最初の質問 (「それはどういう意味ですか?」) と 3 番目の質問 (「最初の条件がこれをカバーしないのはなぜですか?」) に答えています。

私が正しく理解していれば(そうでない場合はお知らせください!)、2つのメソッドがオーバーライド同等であり、元の質問の最初の条件に該当しないケースが1つだけあります。これは、サブクラス メソッドのシグネチャの消去がスーパークラス メソッドのシグネチャと同じであるが、その逆ではない場合です。

Objectしたがって、元の質問の 2 番目の条件は、クラスのパブリック メソッドを「オーバーライド」しようとするときに型パラメーターを追加しようとしたときにのみ有効になります。これをテストするために、未使用の型パラメーターを使用して次の簡単な例を試しました。

public class Foo {
    @Override
    public <T> boolean equals(Object obj) {
        return true;
    }
}

もちろん、このクラスはコンパイルされません。メソッドは実際にはメソッドをオーバーライドせず、equalsメソッドと衝突するからです。しかし、@Override注釈を使用するとコンパイラ エラーも発生します。この例が 2 番目の使用条件を満たしていると仮定するのは間違ってい@Overrideますか? または、必要がないにもかかわらず、コンパイラがこのエラーを生成していますか?

4

2 に答える 2

4

あなたの質問は基本的に設計上の質問であり、JLS は次のように説明しています。

「サブシグネチャの概念は、シグネチャが同一ではないが、一方が他方をオーバーライドできる2つのメソッド間の関係を表現するように設計されています。具体的には、シグネチャがジェネリック型を使用しないメソッドが、そのメソッドのジェネリック化されたバージョンをオーバーライドできるようにします。 .これは、ライブラリの設計者が、ライブラリのサブクラスまたはサブインターフェイスを定義するクライアントとは無関係にメソッドを自由に生成できるようにするために重要です。」

あなたのコードは this の有効な例ではありません。動作する以下のコードを参照してください。

public class SubSignatureTest extends SignatureTest {

    @Override
    public List test(Collection p) {
        return null;
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub

    }

}

class SignatureTest {

    public <T> List<T> test(Collection<T> t) {
        return null;

    }
}

全体のポイントは、消去後にスーパークラスとサブクラスの署名が同じでなければならないということです。

EDIT:オーバーライドの等価性について話すとき、親クラスにはジェネリックメソッドが必要であり、子クラスには非ジェネリックメソッドが必要です。これを説明する例を次に示します。子クラスにはジェネリック メソッドがあるため、以下のコードは機能しません。しばらくの間、java がそれを許可したと仮定してみましょう。その場合、main メソッドの呼び出しは常に失敗します。

class A{
       public int compareTo(Object o){
               return 0;
       }
}

class B extends A implements Comparable<B>{
       public int compareTo(B b){
               return 0;
       }

       public static void main(String[] argv){
               System.out.println(new B().compareTo(new Object()));
       }
}

クラス B メソッドでは、コンパイル後に次のようになります。

public int compareTo(Object x){
    return compareTo((B)x);
  }

つまり、これは常にエラーです: new B().compareTo(new Object()). したがって、親クラスに非ジェネリック メソッドがある場合、Java は子クラスにジェネリック メソッドを許可しません。したがって、オブジェクト クラスのオーバーライド等価メソッドを定義することはできません。

それが明確になることを願っています。

私は投稿http://lists.seas.upenn.edu/pipermail/types-list/2006/001091.htmlを参照用に使用しました。詳細がたくさんあります。

于 2013-04-28T06:43:33.110 に答える