Beim Vergleichen von Objekten in Java führen Sie eine semantische Prüfung durch , indem Sie den Typ und den Identifizierungsstatus der Objekte vergleichen mit:
- selbst (gleiche Instanz)
- selbst (Klon oder rekonstruierte Kopie)
- andere Objekte unterschiedlicher Art
- andere Objekte des gleichen Typs
null
Regeln:
- Symmetrie :
a.equals(b) == b.equals(a)
equals()
immer ergibt true
oder false
, aber nie ein NullpointerException
, ClassCastException
oder jede andere throwable
Vergleich:
- Typprüfung : Beide Instanzen müssen von der zu gleichen Typ, was bedeutet , Sie die aktuellen Klassen für Gleichheit vergleichen haben. Dies wird häufig nicht korrekt implementiert, wenn Entwickler
instanceof
für den Typvergleich verwenden (was nur funktioniert, solange keine Unterklassen vorhanden sind, und die Symmetrieregel verletzt, wenn A extends B -> a instanceof b != b instanceof a)
.
- Semantische Überprüfung des Identifizierungsstatus : Stellen Sie sicher, dass Sie verstehen, anhand welchem Status die Instanzen identifiziert werden. Personen können anhand ihrer Sozialversicherungsnummer identifiziert werden, jedoch nicht anhand der Haarfarbe (kann gefärbt werden), des Namens (kann geändert werden) oder des Alters (kann ständig geändert werden). Nur mit Wertobjekten sollten Sie den vollständigen Status (alle nicht vorübergehenden Felder) vergleichen, andernfalls nur überprüfen, was die Instanz identifiziert.
Für Ihre Person
Klasse:
public boolean equals(Object obj) {
// same instance
if (obj == this) {
return true;
}
// null
if (obj == null) {
return false;
}
// type
if (!getClass().equals(obj.getClass())) {
return false;
}
// cast and compare state
Person other = (Person) obj;
return Objects.equals(name, other.name) && Objects.equals(age, other.age);
}
Wiederverwendbare generische Dienstprogrammklasse:
public final class Equals {
private Equals() {
// private constructor, no instances allowed
}
/**
* Convenience equals implementation, does the object equality, null and type checking, and comparison of the identifying state
*
* @param instance object instance (where the equals() is implemented)
* @param other other instance to compare to
* @param stateAccessors stateAccessors for state to compare, optional
* @param <T> instance type
* @return true when equals, false otherwise
*/
public static <T> boolean as(T instance, Object other, Function<? super T, Object>... stateAccessors) {
if (instance == null) {
return other == null;
}
if (instance == other) {
return true;
}
if (other == null) {
return false;
}
if (!instance.getClass().equals(other.getClass())) {
return false;
}
if (stateAccessors == null) {
return true;
}
return Stream.of(stateAccessors).allMatch(s -> Objects.equals(s.apply(instance), s.apply((T) other)));
}
}
Person
Verwenden Sie für Ihre Klasse diese Dienstprogrammklasse:
public boolean equals(Object obj) {
return Equals.as(this, obj, t -> t.name, t -> t.age);
}