Überschreiben der Methoden equal() und hashCode() in Java
Equals
und hashCode
sind die grundlegenden Methoden, die in der Klasse deklariert Object
und in den Standard-Java-Bibliotheken enthalten sind. Die Methode еquals()
wird verwendet, um Objekte zu vergleichen und hashCode
einen ganzzahligen Code für das Objekt zu generieren. Diese Methoden werden in den Java-Standardbibliotheken häufig zum Einfügen und Abrufen von Objekten in verwendet HashMap
. Die Methode wird auch verwendet, um sicherzustellen, dass nur eindeutige Objekte in anderen Implementierungen equal
gespeichert werden , sowie in allen anderen Fällen, in denen Objekte verglichen werden müssen. Die Standardimplementierung der Methode in der Klasse vergleicht Verweise auf die Speicheradressen, die die Variablen speichern, und gibt nur dann zurück, wenn die Adressen übereinstimmen, d. h. die Variablen auf dasselbe Objekt verweisen. Java empfiehlt, die Methoden und zu überschreiben , wenn erwartet wird, dass der Vergleich der natürlichen Logik oder der Geschäftslogik folgt. Viele Klassen in den Standard-Java-Bibliotheken überschreiben sie, beispielsweise überschreibt die Klasse , sodass sie zurückkehrt, wenn die Inhalte der beiden verglichenen Objekte gleich sind. Die Wrapper-Klasse überschreibt die Methode , um einen numerischen Vergleich durchzuführen usw. Da Java auch auf die und- Methoden angewiesen ist, um ihre und zu vergleichen , bietet Java die folgenden Regeln zum Überschreiben dieser Methoden: HashSet
Set
equals()
java.lang.Object
true
equals()
hashCode()
String
equals
true
Integer
equal
HashMap
HashTable
equals()
hashCode()
key
values
- Reflexivität: Das Objekt muss sich selbst gleich sein.
- Symmetrisch: Wenn
a.equals(b)
es zurückkehrttrue
,b.equals(a)
muss es auch zurückkehrentrue
. - Transitivität: Wenn
a.equals(b)
es zurückkehrttrue
undb.equals(c)
auch zurückkehrttrue
, dannc.equals(a)
muss es auch zurückkehrentrue
. - Konsistenz: Wiederholte Aufrufe einer Methode
equals()
müssen denselben Wert zurückgeben, solange einige der Eigenschaftswerte des Objekts nicht geändert werden. Das heißt, wenn in Java zwei Objekte gleich sind, bleiben sie gleich, solange ihre Eigenschaften unverändert bleiben. - Vergleich
null
: Das Objekt muss überprüft werdennull
. Wenn das Objekt gleich istnull
, sollte die Methode zurückgebenfalse
, nichtNullPointerException
. Beispielsweisea.equals(null)
sollte es zurückgegeben werdenfalse
.
Vereinbarung zwischen equal und hashCode in Java
- Wenn die Objekte in den Ergebnissen der Methodenausführung gleich sind
equals
, müssen siehashcode
gleich sein. - Wenn die Objekte in den Ergebnissen der Methodenausführung nicht gleich sind
equals
, können siehashcode
entweder gleich oder unterschiedlich sein. Um die Leistung zu verbessern, ist es jedoch besser, unterschiedliche Objekte unterschiedliche Codes zurückgeben zu lassen.
So überschreiben Sie die Methode equal in Java
-
@Override public boolean equals(Object obj) { /*1. Überprüfen*/
if (obj == this) { /*und zurück */ return true; }
-
Проверьте ein Objekt на
null
, а также проверьте, чтобы ein Objektы были одного типа. Не делайте проверку с помощьюinstanceof
так Wie такая проверка будет возвращатьtrue
для подклассов и будет работать правильно только в случае если ваш класс объявлен Wieimmutable
. Вместо этого можно использоватьgetClass()
;if (obj == null || obj.getClass() != this.getClass()) { return false; }
-
Объявите переменную типа, который вы сравниваете, и приведите
obj
к этому типу. Потом сравнивайте каждый атрибут типа начиная с численных атрибутов (если имеются) потому что численные атрибуты проверяются быстрей. Сравнивайте атрибуты с помощью операторов И и ИЛИ (так называемыеshort-circuit logical operators
) для объединения проверок с другими атрибутами.Person guest = (Person) obj; return id == guest.id && (firstName == guest.firstName || (firstName != null && firstName.equals(guest.getFirstName()))) && (lastName == guest.lastName || (lastName != null && lastName .equals(guest.getLastName()))); }
/** * Person class with equals and hashcode implementation in Java * @author Javin Paul */
public class Person {
private int id;
private String firstName;
private String lastName;
public int getId() { return id; }
public void setId(int id) { this.id = id;}
public String getFirstName() { return firstName; }
public void setFirstName(String firstName) { this.firstName = firstName; }
public String getLastName() { return lastName; }
public void setLastName(String lastName) { this.lastName = lastName; }
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (obj == null || obj.getClass() != this.getClass()) {
return false;
}
Person guest = (Person) obj;
return id == guest.id
&& (firstName == guest.firstName
|| (firstName != null &&firstName.equals(guest.getFirstName()))) && (lastName == guest.lastName
|| (lastName != null && lastName .equals(guest.getLastName())
));
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((firstName == null) ? 0 : firstName.hashCode()); result = prime * result + id; result = prime * result +
((lastName == null) ? 0 : lastName.hashCode()); return result;
}
}
Распространенные ошибки при переопределении equals в Java
-
Вместо того, чтобы переопределять метод
equals (Override)
программист перегружает его(Overload)
Синтаксис методаequals()
в классеObject
определен Wiepublic boolean equals(Object obj)
, но многие программисты ненароком перегружают метод:public boolean equals(Person obj)
- anstattObject
в качестве аргумента используют Name своего класса (напр. Person). Эту ошибку сложно обнаружить из-заstatic binding
. Таким образом, если вы вызовете этот метод для ein Objektа своего класса, то метод не просто скомпoderруется, а даже сделает это корректно. Однако, если вы положите ваш ein Objekt в коллекцию, напримерArrayList
и вызовете методcontains()
, работа которого основана на методеequals()
, то методcontains
не сможет обнаружить ваш ein Objekt. -
При переопределении метода
equals()
не проверять наnull
переменные, что в конечном итоге заканчиваетсяNullPointerException
при вызовеequals()
. Ниже представлен корректный Code.firstname == guest.firstname || (firstname != null && firstname.equals(guest.firstname));
-
Третья распространенная ошибка это не переопределять метод
hashCode()
, а толькоequals()
. Вы обязаны переопределять оба методаequals()
иhashCode()
в Java. МетодhashCode
используется вhash
-коллекциях(напримерHashSet
), и чем меньше будет коллизий (одинаковый Code при разных ein Objektах) тем эффективнее эти коллекции будут работать с ein Objektами вашего класса. -
Последняя распространенная ошибка программистов в том, что при переопределении метода
equals()
не сохраняется соответствие между методамиequals()
иcompareTo()
, что является неформальным требованием для избежания хранения дубликатов вSet (SortedSet, TreeSet)
.
Подсказки Wie писать в Java метод equals
-
Большинство IDE такие Wie NetBeans, Eclipse и IntelliJ IDEA обеспечивают поддержку генерации методов
equals()
иhashCode()
. В Eclipse нажмите правую кнопку -> source ->generate equals()
иhashCode()
. -
Если в классе есть уникальный бизнес-ключ, то будет достаточно сделать проверку только на gleichtство этих полей. Как в нашем примере “id” - уникальный номер для каждого Person.
-
При переопределении
hashCode()
в Java удостоверьтесь в использовании всех полей, что были использованы в методеequals()
. -
String
und Wrapper-Klassen wieInteger
,Float
undDouble
überschreiben die Methodeequals()
, überschreiben sie jedochStringBuffer
nicht. -
Erstellen Sie Felder nach Möglichkeit
immutable
mithilfefinal
von Variablen in Java. -
Verwenden Sie beim Vergleichen von
String
Objektenequals()
stattdessen den .-Operator==
. -
Zwei Objekte, die logisch gleich sind, aber von unterschiedlichen Objekten geladen werden,
ClassLoader
können nicht gleich sein. Denken Sie daran, dass die Überprüfung mitgetClass()
zu einem Ergebnis führtfalse
, wenn die Loader-Klasse unterschiedlich ist. -
Verwenden Sie
@Override
die Annotation auch für die .-MethodehashCode
, da dies subtile Fehler wie den Rückgabewert derint
.-Methode verhindert. Einige Programmierer geben jedoch zurücklong
.
GO TO FULL VERSION