pk
などのLong属性を使用する@EqualsAndHashCode
アノテーションは、ハッシュベースの構造(HashSetなど)で使用すると、予期しない動作を引き起こす可能性があります。
例えば。:
<strong i="9">@Entity</strong>
@EqualsAndHashCode(of = "pk")
class Foo {
<strong i="10">@Id</strong>
private Long pk;
private LocalDate createdAt;
}
<strong i="13">@Entity</strong>
class Foo {
<strong i="14">@Id</strong>
private Long pk;
private LocalDate createdAt;
public int hashCode() {
int PRIME = true;
int result = 1;
Object $pk = this.getPk();
int result = result * 59 + ($pk == null ? 43 : $pk.hashCode());
return result;
}
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
}
したがって、pk = nullのインスタンスとpk = 43のインスタンスの場合、同じハッシュコードが返され、ハッシュベースの構造では同じと見なされる可能性がありますが、そうではありません。
また、 toString
を使用するOmniFaces ListConverterを使用する場合も、同じ問題が発生します。
ハードコードされた定数ではなく、オブジェクトインスタンスのハッシュコードを返す可能性があります
すでにこのシナリオを採用しましたか、それともこの状況を回避する方法を知っていますか?!
バージョン情報
したがって、pk = nullのインスタンスとpk = 43のインスタンスの場合、同じハッシュコードが返されます。
これは問題ではありません。 さらに、何を選択しても、常にハッシュの衝突が発生します。
Arrays.hashCode
、 String.hashCode
など、多くの場合、不必要に大量の衝突が発生することに注意してください。
ハードコードされた定数ではなく、オブジェクトインスタンスのハッシュコードを返す可能性があります
手動で記述したコードでは、 id
が割り当てられる前に呼び出されないと主張しています。 それは確かに奇妙ですが、すべての選択肢もそうです。
この場合、PKがnullのときにどの値を使用するかを指示できる注釈パラメーターを作成することができます。 デフォルトの場合43。
これにより、開発者はより詳細に制御できるようになります。
@EqualsAndHashCode(of = "pk", ifAnyNull = -1)
したがって、nullであったフィールドには、43ではなく-1が使用されます。
43はおそらく他の数値と同じくらい良く、-1、0、1よりも優れています。設定可能にすることで、非常に低い付加価値のメンテナンス負荷が追加されます。
nullにIdentityハッシュコードを使用すると、equalsコントラクトが破られます。
最も参考になるコメント
43はおそらく他の数値と同じくらい良く、-1、0、1よりも優れています。設定可能にすることで、非常に低い付加価値のメンテナンス負荷が追加されます。
nullにIdentityハッシュコードを使用すると、equalsコントラクトが破られます。