24

プロジェクトでFindBugsを実行すると、上記のエラーがいくつか発生しました。

つまり、equalsのオーバーライドバージョンは、RHSオブジェクトをオーバーライドバージョンが定義されているオブジェクトと同じタイプにキャストします。

ただし、AFAIK Javaではメソッドパラメーターの分散が許可されていないため、より良い設計が可能かどうかはわかりません。そのため、equalsパラメーターに他のタイプを定義することはできません。

私は何か非常に間違ったことをしていますか、それともFindBugsは熱心すぎますか?

この質問を表現する別の方法は次のとおりです。equalsに渡されたオブジェクトがLHSと同じタイプでない場合の正しい動作は何ですか:これはfalseですか、それとも例外があるべきですか?

例えば:

public boolean equals(Object rhs)
{
    MyType rhsMyType = (MyType)rhs; // Should throw exception
    if(this.field1().equals(rhsMyType.field1())... // Or whatever
}
4

4 に答える 4

48

通常、equalsを実装する場合は、引数のクラスが実装クラスと等しい(または互換性がある)かどうかを確認してからキャストできます。このようなもの:

if (getClass() != obj.getClass())
    return false;
MyObj myObj = (MyObj) obj;

このようにすると、FindBugsの警告を防ぐことができます。

コメントに対処するための補足:型安全性をチェックする代わりに
使用することを主張する人もいます。それについては大きな議論があり、クラスの同等性や互換性をチェックできると言ったとき、私は入り込まないように努めていましたが、それを免れることはできないと思います。つまり、これを使用すると、クラスのインスタンスとそのサブクラスのインスタンスの間の同等性をサポートできますが、の対称コントラクトを破るリスクがあります。一般的に、必要であり、何をしているのかを理解していない限り、使用しないことをお勧めします。詳細については、以下を参照してください。instanceofgetClassinstanceofequalsinstanceof

于 2008-12-12T23:10:57.997 に答える
7

あなたはおそらくこのようなことをしているでしょう:

public class Foo {
  // some code

  public void equals(Object o) {
    Foo other = (Foo) o;
    // the real equals code
  }
}

この例では、equals()の引数について何かを想定しています。Foo型であると想定しています。これはそうである必要はありません!文字列を取得することもできます(この場合、ほぼ間違いなくfalseを返す必要があります)。

したがって、コードは次のようになります。

public void equals(Object o) {
  if (!(o instanceof Foo)) {
    return false;
  }
  Foo other = (Foo) o;
  // the real equals code
}

(または、DaveLがgetClass() != o.getClass()言及したより厳格なものを使用します。

このように見ることもできます:

Integer i = new Integer(42);
String s = "fourtytwo";
boolean b = i.equals(s);

ClassCastExceptionこのコードが正常に終了してに設定bする代わりにスローする必要がある理由はありますfalseか?

ClassCastExceptionへの応答としてを投げる.equals()ことは賢明ではありません。それがばかげた質問であっても(「もちろん、文字列はFooと等しくなることはありません!」)、それでも完全に細かい答え( "no" == false)を持つ有効な質問であるためです。

于 2008-12-12T23:15:06.350 に答える
2

上記の findbugs 警告を無視することをお勧めします。実際には、equals が予期しないクラスのオブジェクトで呼び出された場合、それはほぼ間違いなくバグであり、バグですばやく失敗する必要があります。

たとえば、'ArrayList files' があり、files.contains("MyFile.txt") を呼び出した場合、ClassCastException が発生すると便利です。代わりに、Java は false を返すだけであり、そのバグを発見するまでには長い時間がかかる可能性があります。

于 2010-06-10T15:09:51.390 に答える
0

私は次のようにequals(Object)の実装を開始します。

if ((object == null) || !(object instaceof ThisClass)) {
    return false;
}

これにより、FindBugsの警告も防止falseされますが、ThisClassのサブクラスが渡されたときに自動的に返されることはありません。特に、そのequals(Object)メソッドがオーバーライドされていない場合は、等しいと見なされる可能性があります。

于 2008-12-12T23:17:14.740 に答える