Lombok: ハッシュベースの構造で使用した場合のnull属性のhashCode()の問題

作成日 2019年07月19日  ·  3コメント  ·  ソース: projectlombok/lombok

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を使用する場合も、同じ問題が発生します。

ハードコードされた定数ではなく、オブジェクトインスタンスのハッシュコードを返す可能性があります

すでにこのシナリオを採用しましたか、それともこの状況を回避する方法を知っていますか?!

バージョン情報

  • ロンボク=> 1.18.8
  • プラットフォーム=> Windows 10 JDK 11.0.4 IntelliJ

最も参考になるコメント

43はおそらく他の数値と同じくらい良く、-1、0、1よりも優れています。設定可能にすることで、非常に低い付加価値のメンテナンス負荷が追加されます。

nullにIdentityハッシュコードを使用すると、equalsコントラクトが破られます。

全てのコメント3件

したがって、pk = nullのインスタンスとpk = 43のインスタンスの場合、同じハッシュコードが返されます。

これは問題ではありません。 さらに、何を選択しても、常にハッシュの衝突が発生します。

Arrays.hashCodeString.hashCodeなど、多くの場合、不必要に大量の衝突が発生することに注意してください。

ハードコードされた定数ではなく、オブジェクトインスタンスのハッシュコードを返す可能性があります

手動で記述したコードでは、 idが割り当てられる前に呼び出されないと主張しています。 それは確かに奇妙ですが、すべての選択肢もそうです。

この場合、PKがnullのときにどの値を使用するかを指示できる注釈パラメーターを作成することができます。 デフォルトの場合43。

これにより、開発者はより詳細に制御できるようになります。

@EqualsAndHashCode(of = "pk", ifAnyNull = -1)

したがって、nullであったフィールドには、43ではなく-1が使用されます。

43はおそらく他の数値と同じくらい良く、-1、0、1よりも優れています。設定可能にすることで、非常に低い付加価値のメンテナンス負荷が追加されます。

nullにIdentityハッシュコードを使用すると、equalsコントラクトが破られます。

このページは役に立ちましたか?
0 / 5 - 0 評価