Overriding equals() at hashCode() na mga pamamaraan sa Java
Equals
at hashCode
ang mga pangunahing pamamaraan na ipinahayag sa klase Object
at nakapaloob sa mga karaniwang aklatan ng Java. Ang pamamaraan еquals()
ay ginagamit upang ihambing ang mga bagay at hashCode
upang makabuo ng isang integer code para sa bagay. Ang mga pamamaraang ito ay malawakang ginagamit sa mga karaniwang aklatan ng Java kapag naglalagay at kumukuha ng mga bagay sa HashMap
. equal
Ginagamit din ang pamamaraan upang matiyak na ang mga natatanging bagay lamang ang nakaimbak sa HashSet
iba pang Set
mga pagpapatupad, gayundin sa anumang iba pang mga kaso kung saan ang mga bagay ay kailangang ikumpara. Ang default na pagpapatupad ng pamamaraan equals()
sa klase java.lang.Object
ay naghahambing ng mga sanggunian sa mga memory address na iniimbak ng mga variable at ibabalik true
lamang kung ang mga address ay tumutugma, sa madaling salita, ang mga variable ay tumutukoy sa parehong bagay. Inirerekomenda ng Java na i-override ang equals()
at mga pamamaraan hashCode()
kung inaasahan mong gagawin ang paghahambing ayon sa natural na lohika o lohika ng negosyo. Maraming mga klase sa mga karaniwang aklatan ng Java ang nag-o-override sa kanila, halimbawa, ang klase ay String
nag-o-override equals
upang ito ay bumalik true
kung ang mga nilalaman ng dalawang bagay na pinaghahambing ay pareho. Ino-override ng klase ng wrapper Integer
ang paraan equal
upang magsagawa ng paghahambing na numero, at iba pa. Dahil umaasa HashMap
din HashTable
ang Java equals()
at mga pamamaraan hashCode()
upang ihambing ang kanilang key
at values
, nag-aalok ang Java ng mga sumusunod na panuntunan para sa pag-override sa mga pamamaraang ito:
- Reflexivity: Ang bagay ay dapat na katumbas ng sarili nito.
- Symmetrical: kung
a.equals(b)
ito ay bumaliktrue
,b.equals(a)
dapat din itong bumaliktrue
. - Transitivity: kung
a.equals(b)
ito ay bumaliktrue
atb.equals(c)
bumalik dintrue
,c.equals(a)
dapat din itong bumaliktrue
. - Consistency: Ang mga paulit-ulit na tawag sa isang paraan
equals()
ay dapat magbalik ng parehong halaga hangga't ang ilan sa mga value ng property ng object ay hindi nabago. Iyon ay, kung ang dalawang bagay ay pantay sa Java, kung gayon sila ay magiging pantay hangga't ang kanilang mga katangian ay mananatiling hindi nagbabago. - Paghahambing
null
: Dapat suriin ang bagay para sanull
. Kung ang bagay ay katumbas ngnull
, kung gayon ang pamamaraan ay dapat bumalikfalse
, hindiNullPointerException
. Halimbawa,a.equals(null)
dapat itong bumalikfalse
.
Kasunduan sa pagitan ng equals at hashCode sa Java
- Kung ang mga bagay ay pantay sa mga resulta ng method execution
equals
,hashcode
dapat pareho ang mga ito. - Kung ang mga bagay ay hindi pantay-pantay sa mga resulta ng pagpapatupad ng pamamaraan
equals
, maaari silanghashcode
maging pareho o magkaiba. Gayunpaman, upang mapabuti ang pagganap, mas mahusay na magkaroon ng iba't ibang mga bagay na nagbabalik ng iba't ibang mga code.
Paano i-override ang katumbas na pamamaraan sa Java
-
@Override public boolean equals(Object obj) { /*1. Check*/
if (obj == this) { /*and return */ return true; }
-
Suriin ang bagay para sa
null
, at suriin din kung ang mga bagay ay pareho ang uri. Huwag suriininstanceof
dahil babalik itotrue
para sa mga subclass at gagana lamang nang tama kung ang iyong klase ay idineklara bilangimmutable
. Pwede mong gamitingetClass()
;if (obj == null || obj.getClass() != this.getClass()) { return false; }
-
Magdeklara ng variable ng uri na iyong inihahambing at i-cast
obj
sa ganoong uri. Pagkatapos ay ihambing ang bawat uri ng attribute, simula sa mga numeric na attribute (kung mayroon man) dahil ang mga numeric na attribute ay mas mabilis na sinusuri. Ihambing ang mga katangian gamit ang AND at OR operator (tinatawag nashort-circuit logical operators
) upang pagsamahin ang mga pagsusuri sa iba pang mga katangian.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;
}
}
Mga Karaniwang Pagkakamali Kapag ang Overriding ay katumbas sa Java
-
Sa halip na i-override ang pamamaraan,
equals (Override)
na-overload ito ng programmer.(Overload)
Ang syntax ng isang pamamaraanequals()
sa isang klaseObject
ay tinukoy bilangpublic boolean equals(Object obj)
, ngunit maraming programmer ang hindi sinasadyang na-overload ang pamamaraan:public boolean equals(Person obj)
- sa halip naObject
gamitin ang pangalan ng klase nito bilang argumento (hal. Tao). Ang error na ito ay mahirap matukoy dahil sastatic binding
. Kaya, kung tatawagin mo ang pamamaraang ito sa isang bagay ng iyong klase, ang pamamaraan ay hindi lamang mag-compile, ngunit gagawin pa rin ito ng tama. Gayunpaman, kung ilalagay mo ang iyong bagay sa isang koleksyon, halimbawa,ArrayList
at tumawag sa isang pamamaraancontains()
na ang operasyon ay batay sa pamamaraanequals()
,contains
hindi matukoy ng pamamaraan ang iyong bagay. -
Kapag nag-o-override sa isang paraan,
equals()
huwag suriin kung maynull
mga variable, na sa huli ay mapupuntaNullPointerException
kapag tumatawagequals()
. Nasa ibaba ang tamang code.firstname == guest.firstname || (firstname != null && firstname.equals(guest.firstname));
-
Ang pangatlong karaniwang pagkakamali ay hindi ang pag-override sa pamamaraan
hashCode()
, ngunit angequals()
. Kinakailangan mong i-override ang parehong mga pamamaraan sa Javaequals()
din .hashCode()
Ang pamamaraanhashCode
ay ginagamit sahash
-collections (halimbawaHashSet
), at mas kaunting mga banggaan ang mayroon (parehong code para sa iba't ibang mga bagay), mas mahusay na gagana ang mga koleksyong ito sa mga bagay ng iyong klase. -
Ang huling karaniwang pagkakamali ng mga programmer ay kapag nag-o-override sa isang paraan,
equals()
ang pagmamapa sa pagitan ng mga pamamaraanequals()
at hindi pinapanatilicompareTo()
, na isang impormal na kinakailangan upang maiwasan ang pag-imbak ng mga duplicate saSet (SortedSet, TreeSet)
.
Mga tip sa kung paano isulat ang katumbas na pamamaraan sa Java
-
Karamihan sa mga IDE tulad ng NetBeans, Eclipse at IntelliJ IDEA ay nagbibigay ng suporta para sa pagbuo ng mga pamamaraan
equals()
athashCode()
. Sa Eclipse, i-right click -> source ->generate equals()
athashCode()
. -
Kung ang klase ay may natatanging business key, magiging sapat na upang suriin lamang ang pagkakapantay-pantay ng mga field na ito. Tulad ng sa aming halimbawa, ang "id" ay isang natatanging numero para sa bawat Tao.
-
Kapag nag-o-override
hashCode()
sa Java, tiyaking gamitin ang lahat ng field na ginamit sa pamamaraanequals()
. -
String
at mga klase ng wrapper tulad ngInteger
,Float
atDouble
i-override ang methodequals()
, ngunitStringBuffer
hindi na-override. -
Hangga't maaari, gumawa ng mga field
immutable
gamitfinal
ang mga variable sa Java. -
Kapag naghahambing
String
ng mga bagay, gamitinequals()
sa halip ang operator na==
. -
Ang dalawang bagay na lohikal na magkapareho ngunit na-load mula sa magkaibang mga bagay
ClassLoader
ay hindi maaaring magkapantay. Tandaan na ang pagsuri sagetClass()
ay babalikfalse
kung ang klase ng loader ay iba. -
Gamitin
@Override
din ang anotasyon sa pamamaraang .hashCode
, dahil pinipigilan nito ang mga banayad na error tulad ng halaga ng pagbabalik ngint
. Gayunpaman, nagbabalik ang ilang programmerlong
.
GO TO FULL VERSION