Java тіліндегі equals() және hashCode() әдістерін қайта анықтау
Equals
және hashCode
олар сыныпта жарияланған Object
және стандартты Java кітапханаларында қамтылған іргелі әдістер болып табылады. Әдіс нысандарды салыстыру және an object үшін бүтін codeты жасау үшін еquals()
қолданылады . hashCode
Бұл әдістер Java стандартты кітапханаларында an objectілерді кірістіру және алу кезінде кеңінен қолданылады HashMap
. Әдіс басқа іске асыруларда, сондай-ақ an objectілерді салыстыруды қажет ететін кез келген басқа жағдайларда equal
ғана бірегей нысандардың сақталуын қамтамасыз ету үшін қолданылады . Сыныптағы әдістің әдепкі орындалуы айнымалылар сақтайтын жад мекенжайларына сілтемелерді салыстырады және мекенжайлар сәйкес келсе ғана қайтарады, басқаша айтқанда, айнымалылар бір нысанға сілтеме жасайды. Салыстыру табиғи логикаға немесе іскерлік логикаға сәйкес орындалады деп күтсеңіз, Java және әдістерді қайта анықтауды ұсынады. Стандартты Java кітапханаларындағы көптеген сыныптар оларды қайта анықтайды, мысалы, салыстырылатын екі нысанның мазмұны бірдей болса, оны қайтаратындай класс қайта анықтайды . Қаптама класы сандық салыстыруды орындау әдісін қайта анықтайды және т.б. Java сондай -ақ оларды және салыстыру әдістеріне сүйенетіндіктен , Java осы әдістерді қайта анықтау үшін келесі ережелерді ұсынады: HashSet
Set
equals()
java.lang.Object
true
equals()
hashCode()
String
equals
true
Integer
equal
HashMap
HashTable
equals()
hashCode()
key
values
- Рефлексивтілік: an object өзіне тең болуы керек.
- Симметриялық: егер
a.equals(b)
ол қайтарсаtrue
, ондаb.equals(a)
ол да қайтарылуы керекtrue
. - Транзитивтілік: егер
a.equals(b)
ол қайтарсаtrue
жәнеb.equals(c)
де қайтарсаtrue
, ондаc.equals(a)
ол да қайтарылуы керекtrue
. - Жүйелілік: әдіске қайталанатын қоңыраулар
equals()
нысанның кейбір сипат мәндері өзгертілмесе, бірдей мәнді қайтаруы керек. Яғни, Java тілінде екі нысан тең болса, олардың қасиеттері өзгеріссіз қалғанша олар тең болады. - Салыстыру
null
: an objectіні тексеру керекnull
. Егер нысан тең болсаnull
, онда әдісfalse
емес қайтару керекNullPointerException
. Мысалы,a.equals(null)
ол қайтарылуы керекfalse
.
Java тіліндегі тең және hashCode арасындағы келісім
- Егер нысандар әдісті орындау нәтижелері бойынша тең болса
equals
, онда оларhashcode
бірдей болуы керек. - Егер нысандар әдісті орындау нәтижелері бойынша тең болмаса
equals
, онда оларhashcode
бірдей немесе әртүрлі болуы мүмкін. Дегенмен, өнімділікті жақсарту үшін әртүрлі нысандардың әртүрлі codeтарды қайтаратыны жақсы.
Java тіліндегі тең әдісті қалай қайта анықтауға болады
-
@Override public boolean equals(Object obj) { /*1. Check*/
if (obj == this) { /*and return */ return true; }
-
Проверьте an object на
null
, а также проверьте, чтобы an objectы были одного типа. Не делайте проверку с помощьюinstanceof
так How такая проверка будет возвращатьtrue
для подклассов и будет работать правильно только в случае если ваш класс объявлен Howimmutable
. Вместо этого можно использовать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
определен Howpublic boolean equals(Object obj)
, но многие программисты ненароком перегружают метод:public boolean equals(Person obj)
- instead ofObject
в качестве аргумента используют Name своего класса (напр. Person). Эту ошибку сложно обнаружить из-заstatic binding
. Таким образом, если вы вызовете этот метод для an object своего класса, то метод не просто скомпorруется, а даже сделает это корректно. Однако, если вы положите ваш an object в коллекцию, напримерArrayList
и вызовете методcontains()
, работа которого основана на методеequals()
, то методcontains
не сможет обнаружить ваш an object. -
При переопределении метода
equals()
не проверять наnull
переменные, что в конечном итоге заканчиваетсяNullPointerException
при вызовеequals()
. Ниже представлен корректный code.firstname == guest.firstname || (firstname != null && firstname.equals(guest.firstname));
-
Третья распространенная ошибка это не переопределять метод
hashCode()
, а толькоequals()
. Вы обязаны переопределять оба методаequals()
иhashCode()
в Java. МетодhashCode
используется вhash
-коллекциях(напримерHashSet
), и чем меньше будет коллизий (одинаковый code при разных an objectх) тем эффективнее эти коллекции будут работать с an objectми вашего класса. -
Последняя распространенная ошибка программистов в том, что при переопределении метода
equals()
не сохраняется соответствие между методамиequals()
иcompareTo()
, что является неформальным требованием для избежания хранения дубликатов вSet (SortedSet, TreeSet)
.
Подсказки How писать в Java метод equals
-
Большинство IDE такие How NetBeans, Eclipse и IntelliJ IDEA обеспечивают поддержку генерации методов
equals()
иhashCode()
. В Eclipse нажмите правую кнопку -> source ->generate equals()
иhashCode()
. -
Если в классе есть уникальный бизнес-ключ, то будет достаточно сделать проверку только на equalsство этих полей. Как в нашем примере “id” - уникальный номер для каждого Person.
-
При переопределении
hashCode()
в Java удостоверьтесь в использовании всех полей, что были использованы в методеequals()
. -
String
Integer
және , сияқты орауыш сыныптарыFloat
жәнеDouble
әдісті қайта анықтайдыequals()
, бірақStringBuffer
қайта анықтамайды. -
Мүмкіндігінше Java тіліндегі айнымалы мәндерді
immutable
пайдаланып өрістер жасаңыз.final
-
String
Нысандарды салыстыру кезіндеequals()
орнына . операторын пайдаланыңыз==
. -
Логикалық жағынан тең, бірақ әртүрлі нысандардан жүктелген екі нысан
ClassLoader
тең бола алмайды. Есіңізде болсын, жүктеуші класы басқаша болса, тексеруgetClass()
қайтарылады .false
-
@Override
Аннотацияны .әдісінде де пайдаланыңызhashCode
, себебі бұл қайтару мәні сияқты нәзік қателерді болдырмайды.Бірақint
кейбір бағдарламашылар қайтарадыlong
.
GO TO FULL VERSION