9

この質問は、特に、多数のフィールドを持つオブジェクトのequals()メソッドのオーバーライドに関連しています。まず、この大きなオブジェクトは、オブジェクト指向の原則に違反せずに複数のコンポーネントに分割することはできないため、「xフィールドを超えるクラスはありません」と言っても役に立ちません。

次に、フィールドの1つが等しいかどうかを確認するのを忘れたときに、問題が発生しました。したがって、私のequalsメソッドは正しくありませんでした。それから私はリフレクションを使うことを考えました:

--code removed because it was too distracting--

この投稿の目的は、必ずしもコードをリファクタリングすることではなく(これは、私が使用しているコードでもありません)、代わりに、これが良いアイデアであるかどうかについての入力を取得することです。

長所:

  • 新しいフィールドが追加されると、自動的に含まれます
  • このメソッドは、30ifステートメントよりもはるかに簡潔です。

短所:

  • 新しいフィールドが追加されると、それは自動的に含まれますが、これは望ましくない場合があります
  • パフォーマンス:これは遅くする必要があります。プロファイラーを分割する必要はありません。
  • 比較で無視する特定のフィールドをホワイトリストに登録するのは少し醜いです

何かご意見は?

4

9 に答える 9

13

パフォーマンス上の理由でホワイトリストに登録したい場合は、比較するフィールドを示すために注釈を使用することを検討してください。また、フィールドにの適切な実装がない場合、この実装は機能しませんequals()

PSのためにこのルートに行く場合は、のためequals()に同様のことをすることを忘れないでくださいhashCode()

PPSあなたはすでにHashCodeBuilderEqualsBuilderを検討していると思います。

于 2008-09-23T23:49:02.497 に答える
9

Eclipse、FFSを使用してください!

hashCodeとequalsメソッドを削除します。

ファイルを右クリックします。

[ソース]->[ハッシュコードの生成]を選択します。

終わり!反射の心配はもうありません。

追加されたフィールドごとに繰り返します。アウトラインビューを使用して2つのメソッドを削除し、Eclipseにそれらを自動生成させます。

于 2008-10-06T12:43:50.437 に答える
5

リフレクション アプローチを使用する場合でも、EqualsBuilder はあなたの味方です。

 public boolean equals(Object obj) {
    return EqualsBuilder.reflectionEquals(this, obj);
 }
于 2008-09-24T11:43:10.237 に答える
2

気になる方は以下を参考にしてください。

1/ フィールドを追加/削除するときに、等価性をチェックするための一連の if ステートメントを更新するのを忘れている。

2/ equals() メソッドでこれを行うパフォーマンス。

次のことを試してください。

a/ equals() メソッドで if ステートメントの長いシーケンスを使用するように戻します。

b/ フィールドのリスト (文字列配列内) を含み、そのリストを現実 (つまり、反映されたフィールド) に対してチェックする単一の関数を用意します。一致しない場合、例外がスローされます。

c/ このオブジェクトのコンストラクターで、この関数への同期された 1 回限りの呼び出しを行います (シングルトン パターンに似ています)。つまり、これがこのクラスによって構築された最初のオブジェクトである場合は、上記 (b) で説明したチェック関数を呼び出します。

反映されたフィールドに一致するように if ステートメントを更新していない場合、プログラムを実行すると例外がすぐに明らかになります。次に、if ステートメントを修正し、上記 (b) のフィールド リストを更新します。

その後のオブジェクトの構築ではこのチェックは行われず、equals() メソッドは可能な最大速度で実行されます。

試してみてください。このアプローチで実際の問題を見つけることはできませんでした (StackOverflow にはより大きな心が存在する可能性があります)。1 回限りの動作のために各オブジェクトの構築に追加の条件チェックがありますが、それはかなりマイナーなようです。

十分に努力すれば、if ステートメントがフィールド リストおよび反映されたフィールドと一致しない可能性がありますが、例外により、フィールド リストが反映されたフィールドと確実に一致し、if ステートメントとフィールドを確実に更新することができます。同時にリストします。

于 2008-09-24T02:08:27.890 に答える
1

equalsメソッドでは、必要なフィールドと不要なフィールドにいつでも注釈を付けることができます。これは、簡単で簡単な変更である必要があります。

パフォーマンスは明らかにオブジェクトが実際に比較される頻度に関係していますが、多くのフレームワークはハッシュマップを使用するため、equalsが思った以上に使用されている可能性があります。

また、ハッシュマップについて言えば、hashCodeメソッドでも同じ問題があります。

最後に、本当にすべてのフィールドを比較して平等である必要がありますか?

于 2008-09-23T23:51:48.653 に答える
1

注釈を使用して、チェックからフィールドを除外できます

例えば

@IgnoreEquals
String fieldThatShouldNotBeCompared;

そしてもちろん、ジェネリック equals メソッドでアノテーションの存在を確認します。

于 2008-10-06T11:44:25.423 に答える
1

コードにいくつかのバグがあります。

  1. thisobjが同じクラスであると想定することはできません。実際、obj他のクラスであることは明示的に許可されています。あなたはから始めることができますが、これはif ( ! obj instanceof myClass ) return false;まだ正しくありません.objthis
  2. シンプルなnull値をサポートする必要がありますobjif ( obj == null ) return false;
  3. null空の文字列を同等に扱うことはできません。代わりnullに特別に扱います。ここでの最も簡単な方法は、比較することから始めることField.get(obj) == Field.get(this)です。両方が等しい場合、または両方がたまたま同じオブジェクトを指している場合、これは高速です。(注: これは最適化でもあり、これは遅いルーチンであるため必要です。) これが失敗した場合は、fast を使用してif ( Field.get(obj) == null || Field.get(this) == null ) return false;、正確に 1 つが であるケースを処理できますnull。最後に、通常の を使用できますequals()
  4. 使っていませんfoundMismatch

私はハンクに同意し[HashCodeBuilder][1][EqualsBuilder][2]より良い方法です。定型コードが多くなく、保守が簡単で、これらの問題をすべて回避できます。

于 2008-09-24T00:02:48.533 に答える
0

フィールドの名前にアクセスできる場合は、含めたくないフィールドを常に「local」や「nochk」などで始めることを標準にしてみませんか。

次に、これで始まるすべてのフィールドをブラックリストに登録します(コードはそれほど醜いものではありません)。

少し遅いのは間違いありません。更新のしやすさと実行速度を入れ替えるかどうかを決める必要があります。

于 2008-09-23T23:52:26.857 に答える
-1

org.apache.commons.EqualsBuilder を見てください:

http://commons.apache.org/proper/commons-lang/javadocs/api-3.2/org/apache/commons/lang3/builder/EqualsBuilder.html

于 2008-09-24T00:05:53.253 に答える