Die @EqualsAndHashCode
-Anmerkung, die ein Long-Attribut wie pk
verwendet, kann bei Verwendung mit Hash-basierten Strukturen (wie HashSet) zu einem unerwarteten Verhalten führen.
z.B.:
<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());
}
}
Wenn also die Instanz mit pk = null und andere mit pk = 43, gibt sie den gleichen Hash-Code zurück und kann auf der Hash-basierten Struktur als gleich angesehen werden, was sie nicht sind.
Und im Fall der Verwendung von OmniFaces ListConverter, die toString
verwenden, haben wir das gleiche Problem.
Geben Sie möglicherweise eher einen Hashcode der Objektinstanz als eine fest codierte Konstante zurück
Haben Sie dieses Szenario bereits angenommen oder kennen Sie eine Möglichkeit, diese Situation zu umgehen?!
Versions Information
Wenn also die Instanz mit pk = null und andere mit pk = 43, gibt sie denselben Hash-Code zurück
Das spielt keine Rolle. Außerdem wird es immer Hash-Kollisionen geben, egal, was Sie wählen.
Beachten Sie, dass Arrays.hashCode
, String.hashCode
und viele andere Tonnen von Kollisionen erzeugen, eher unnötig.
Geben Sie möglicherweise eher einen Hashcode der Objektinstanz als eine fest codierte Konstante zurück
In meinem manuell geschriebenen Code behaupte ich, dass er nicht aufgerufen wird, bevor ein id
zugewiesen wird. Das ist sicherlich seltsam, aber alle Alternativen sind es auch.
Es wäre möglich, einen Anmerkungsparameter zu erstellen, der angibt, welcher Wert verwendet werden sollte, wenn der PK in diesem Fall null ist. Standardmäßig 43.
Dies würde dem Entwickler mehr Kontrolle geben.
@EqualsAndHashCode(of = "pk", ifAnyNull = -1)
Daher wird für jedes Feld, das null war, -1 anstelle von 43 verwendet
43 ist wahrscheinlich so gut wie jede andere Zahl und besser als -1, 0 und 1. Wenn man sie konfigurierbar macht, erhöht sich der Wartungsaufwand für einen sehr geringen Mehrwert.
Die Verwendung des Identity-Hashcodes für null würde den Equals-Vertrag brechen.
Hilfreichster Kommentar
43 ist wahrscheinlich so gut wie jede andere Zahl und besser als -1, 0 und 1. Wenn man sie konfigurierbar macht, erhöht sich der Wartungsaufwand für einen sehr geringen Mehrwert.
Die Verwendung des Identity-Hashcodes für null würde den Equals-Vertrag brechen.