Object中equals方法的實(shí)現(xiàn)原理:
equals方法用于檢測(cè)一個(gè)對(duì)象是否與另外一個(gè)對(duì)象相等。而在Object類中這個(gè)方法實(shí)際上是判斷兩個(gè)對(duì)象是否具有相同他的引用,如果有信不,則相等吃嘿。
Public Boolean equals(object obj){
return (this == obj)
}
所有對(duì)象都擁有標(biāo)識(shí)(內(nèi)存地址)和狀態(tài)(數(shù)據(jù)),同時(shí)“==”比較兩個(gè)對(duì)象的內(nèi)存地址币叹,所以說Object的equals()方法是比較兩個(gè)對(duì)象的內(nèi)存地址是否相等姨拥。
若object1.equals(object2)為true绅喉,標(biāo)識(shí)objects1和object2實(shí)際上是引用同一個(gè)對(duì)象
equals()與 == 的區(qū)別:
默認(rèn)情況下從超類object繼承而來的equals()方法與“==”是完全等價(jià)的,比較的都是對(duì)像的內(nèi)存地址叫乌,但是我們可以通過重寫equals方法柴罐,使其按照我們的需求的方式進(jìn)行比較,比如String類重寫了equals方法憨奸,比較的是字符的序列革屠,而不再是內(nèi)存地址。
equals方法的特性:
- 自反性(x.equals(x)必須返回true)
- 對(duì)稱性(x.equals(y)返回true時(shí)排宰,y.equals(x)也必須返回true)
- 傳遞性(x.equals(y)和y.equals(z)都返回true時(shí)似芝,x.equals(z)也必須返回true)
- 一致性(當(dāng)x和y引用的對(duì)象信息沒有被修改時(shí),多次調(diào)用x.equals(y)應(yīng)該得到同樣的返回值)
- 對(duì)于任何非null值的引用x额各,x.equals(null)必須返回false国觉。
為什么重寫equal()的同時(shí)還要重寫hashCode():
hashCode是散列碼吧恃,哈希碼虾啦,是由對(duì)象到處的一個(gè)整型值,散列碼是沒有規(guī)律的,如果x與y是兩個(gè)不同的對(duì)象傲醉,那么它們的散列碼基本不會(huì)相同蝇闭。在Java中,我們可以使用hashCode()來獲取對(duì)象的散列碼硬毕,其值就是對(duì)象的存儲(chǔ)地址呻引,這個(gè)方法在Object類中聲明,因此所有的子類都含有這個(gè)方法吐咳。
《Effective Java》中對(duì)hashCode的約定:
1.在Java應(yīng)用程序執(zhí)行期間逻悠,如果equals方法比較中所用的信息沒有被修改,那么在同一個(gè)對(duì)象多次調(diào)用hashCode方法必須一致地返回相同地整數(shù)韭脊。如果多次執(zhí)行同一個(gè)應(yīng)用童谒,不要求該整數(shù)必須相同。
2.如果兩個(gè)對(duì)象通過調(diào)用equals方法是相等的沪羔,那么這兩個(gè)對(duì)象調(diào)用hashCode方法必須返回相同的整數(shù)
3.如果兩個(gè)對(duì)象通過調(diào)用equals方法是不相同的饥伊,不要求這兩個(gè)對(duì)像調(diào)用hashCode方法必須返回不同的整數(shù)。但是程序員應(yīng)該意識(shí)到對(duì)不同的對(duì)象產(chǎn)生不同的hash值可以提供哈希表的性能蔫饰。
《Java編程思想》中對(duì)第一條進(jìn)行說明:
“設(shè)計(jì)hashCode()時(shí)最重要的因素就是:無論何時(shí)琅豆,對(duì)同一個(gè)對(duì)象調(diào)用hashCode()都應(yīng)該產(chǎn)生同樣的值。如果在講一個(gè)對(duì)象用put()添加進(jìn)HashMap時(shí)產(chǎn)生一個(gè)HashCode值篓吁,而用get()取出時(shí)卻產(chǎn)生了另一個(gè)hashCode值茫因,那么就無法獲取該對(duì)象了。所以如果你的hashCode方法依賴于對(duì)象中易變的數(shù)據(jù)杖剪,用戶就要當(dāng)心了节腐,因?yàn)榇藬?shù)據(jù)發(fā)生變化時(shí),hashCode()方法就會(huì)生成一個(gè)不同的散列碼摘盆∫砣福”
由上可知,在Object類中孩擂,hashCode方法是通過Object對(duì)象的地址計(jì)算出來的狼渊,因?yàn)镺bject對(duì)象只與自身相等,多以同一個(gè)對(duì)象的地址總是相等的类垦,計(jì)算取得的哈希碼也必然相等狈邑,對(duì)于不同的對(duì)象,由于地址不同蚤认,所獲取的哈希碼自然也不會(huì)相等米苹。所以如果一個(gè)類重寫了equals方法,但沒有重寫hashCode方法砰琢,違反了第2條規(guī)定蘸嘶。
重寫equals()中g(shù)etClass與instanceof的區(qū)別:
重寫equals()方法時(shí)良瞧,一般推薦使用getClass來進(jìn)行類型判斷,除非所有的子類有統(tǒng)一的語義才使用instanceof训唱。Instanceof的作用時(shí)判斷左邊對(duì)象是否為右邊類的實(shí)例褥蚯,返回boolean類型的數(shù)據(jù)】鲈觯可以用來判斷繼承中的子類的實(shí)例是否為父類的實(shí)現(xiàn)赞庶。
實(shí)現(xiàn)高質(zhì)量的equals方法的訣竅:
- 使用==操作符檢查:參數(shù)是否為這個(gè)對(duì)象的引用
- 使用instanceof操作符檢查:參數(shù)是否為正確的類型
- 對(duì)于類中的關(guān)鍵屬性,檢查參數(shù)傳入對(duì)象的屬性是否與之相配
- 編寫完equals方法后澳骤,問自己它是否滿足對(duì)稱性歧强,傳遞性,一致性
- 重寫equals時(shí)總是要重寫hashCode
- 不要將equals方法參數(shù)中的object對(duì)象替換為其他的類型为肮,在重寫時(shí)不要忘記@override注解
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Person))
return false;
Person p = (Person) o;
return name.equals(p.name) && age == p.age;
}