26

ジェネリック型を受け入れるクラスがあり、メソッドを邪魔にならない方法でオーバーライドしたいequals(つまり、クリーンに見え、コードの量が最小限であるが、非常に一般的なユース ケースの場合)。

今、私はこのようなものを持っています:

public class SingularNode<T> {
    private T value;

    @SuppressWarnings("unchecked")
    @Override
    public boolean equals(Object other){
        if(other instanceof SingularNode<?>){
            if(((SingularNode<T>)other).value.equals(value)){
                return true;
            }
        }
        return false;
    }
}

私が推測しているのは、かなり欠陥のあるものです。オブジェクトに対してキャストを行っているためSingularNode<T>エラーがスローotherされる可能性があります。

もう1つのことは、私がそうするとき、if(other instanceof SingularNode<?>)実際には正確に正しいことをチェックしていないということです. Ttypeではなく typeに対してチェックしたいのです??をにしようとすると、次のTようなエラーが発生します。

パラメータ化された型に対して instanceof チェックを実行できませんSingularNode<T>SingularNode<?>それ以上のジェネリック型情報は実行時に消去されるため、代わりにフォームを使用してください。

どうすればこれを回避できますか? 何か方法はありますT.class.isInstance(other);か?

次のような本当に醜いハックソリューションが1つあると思います。

@SuppressWarnings("unchecked")
public boolean isEqualTo(Class<?> c, Object obj){
    if(c.isInstance(obj) && c.isInstance(this)){
        if(((SingularNode<T>)obj).value.equals(value)){
            return true;
        }
    }
    return false;
}

しかし、それは余分なメソッド パラメーターを使用すると非常に厄介に見えます。また、equalsis のような組み込み関数でもありません。

ジェネリックを理解している人はこれを説明してください。お分かりのように、私は Java にそれほど精通していないので、もう少し詳しく説明してください。

4

5 に答える 5

32

このバージョンでは警告が表示されません

public boolean equals(Object other){
    if (other instanceof SingularNode<?>){
        if ( ((SingularNode<?>)other).value.equals(value) ){
            return true;
        }
    }
    return false;
}

それにキャストしSingularNode<T>ても何の役にも立ちませTObject

ジェネリックが Java でどのようにコンパイルされるかについて詳しくは、次の URL をご覧ください。

https://docs.oracle.com/javase/tutorial/java/generics/erasure.html

于 2013-05-05T09:23:57.583 に答える
6

Evgeniy の解決策Michal の推論は正しいです。ここでは型について心配する必要はありませんT。その理由は、equalsメソッドが正しく機能するためにジェネリックに依存していないためです。代わりに、によって宣言されObjectObject. したがって、渡されたものの実行時の型をチェックする責任があります。

thisであり、SingularNode<String>それを a と比較すると、引数を指定して呼び出すと正しく が返されるため、完全に問題ありません。SingularNode<Integer>((SingularNode<?>)other).value.equals(value)Integer.equalsStringfalse

于 2013-05-05T16:08:45.670 に答える
1

ここに答えを入れてコードを入れます..

あなたの例では、次の equals 実装によると、 (疑似コードで)Integer(5).equals(Char('k'))があります。falsejava.lang.Integer

public boolean equals(Object obj) {
    if (obj instanceof Integer) {
        return value == ((Integer)obj).intValue();
    }
    return false;
}

そうすれば、キャストについて心配する必要はありません。

于 2013-05-05T09:18:06.560 に答える