Lombok: Masalah dengan kode hash() pada atribut null saat digunakan pada struktur berbasis hash

Dibuat pada 19 Jul 2019  ·  3Komentar  ·  Sumber: projectlombok/lombok

Anotasi @EqualsAndHashCode yang menggunakan atribut Long seperti pk dapat menyebabkan beberapa perilaku yang tidak terduga saat digunakan dengan struktur berbasis hash (seperti HashSet).

misalnya.:

<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());
    }
}

Jadi ketika instance dengan pk = null dan lainnya dengan pk = 43, itu akan mengembalikan kode hash yang sama dan itu dapat dianggap sama pada struktur berbasis hash, yang sebenarnya tidak.

Dan dalam kasus untuk menggunakan OmniFaces ListConverter yang menggunakan toString kami memiliki masalah yang sama.

Mungkin mengembalikan kode hash dari instance objek daripada konstanta hardcoded

Apakah Anda sudah mengambil skenario ini, atau apakah Anda tahu cara untuk mengatasi situasi ini?!

Informasi versi

  • Lombok => 1.18.8
  • Platform => Windows 10 JDK 11.0.4 IntelliJ

Komentar yang paling membantu

43 mungkin sama bagusnya dengan nomor lainnya, dan lebih baik dari -1, 0 dan 1. Membuatnya dapat dikonfigurasi menambah beban pemeliharaan untuk nilai tambah yang sangat rendah.

Menggunakan kode hash Identity untuk null akan melanggar kontrak yang sama.

Semua 3 komentar

Jadi ketika instance dengan pk = null dan lainnya dengan pk = 43, itu akan mengembalikan kode hash yang sama

Ini tidak masalah. Selain itu, akan selalu ada tabrakan hash, apa pun yang Anda pilih.

Perhatikan bahwa Arrays.hashCode , String.hashCode dan banyak lainnya menghasilkan banyak tabrakan, yang sebenarnya tidak perlu.

Mungkin mengembalikan kode hash dari instance objek daripada konstanta hardcoded

Dalam kode saya yang ditulis secara manual, saya menegaskan bahwa itu tidak dipanggil sebelum id ditetapkan. Itu pasti aneh, tapi begitu juga semua alternatif.

Dimungkinkan untuk membuat parameter anotasi yang dapat memberi tahu nilai mana yang harus digunakan ketika PK adalah nol, dalam kasus ini. Untuk standar 43.

Ini akan memberi lebih banyak kontrol kepada pengembang.

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

Jadi itu akan menggunakan -1 sebagai gantinya 43, untuk bidang apa pun yang nol

43 mungkin sama bagusnya dengan nomor lainnya, dan lebih baik dari -1, 0 dan 1. Membuatnya dapat dikonfigurasi menambah beban pemeliharaan untuk nilai tambah yang sangat rendah.

Menggunakan kode hash Identity untuk null akan melanggar kontrak yang sama.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat