覆蓋equals時(shí)請(qǐng)遵守通用約定

第8條:覆蓋equals時(shí)請(qǐng)遵守通用約定


1. 前言

覆蓋equals方法看似很簡(jiǎn)單,但是有許多覆蓋方法或?qū)е洛e(cuò)誤,避免這些錯(cuò)誤最直接的方法就是不覆蓋equals,這樣,沒(méi)有對(duì)象就只與自己相等。

2. 不需要覆蓋equals方法的情況有哪些?

(1)類的每一個(gè)實(shí)體本質(zhì)上都是唯一的。比如Thread類,每一個(gè)實(shí)體都是唯一的,所以不需要覆蓋equals方法。

(2)不關(guān)心類是否提供了“邏輯相等”的測(cè)試功能。·

(3)父類已經(jīng)覆蓋了equals方法,并且在子類中這些方法同樣適用。

(4)類是私有的或是包級(jí)私有的,可以確定equals方法永遠(yuǎn)不會(huì)被調(diào)用。其實(shí)這種情況我們還是應(yīng)該覆蓋equals的方法的,將equals方法設(shè)置成不可訪問(wèn)的。像下面這樣:

@Override
public boolean equals(Object o) {
    throw new AssertionError();
}

3. 需要覆蓋equals方法的情況

一般來(lái)說(shuō),“值類”都是需要覆蓋equals方法的。
什么類屬于“值類”?
對(duì)于那些只關(guān)心內(nèi)容,不關(guān)心是否指向同一片內(nèi)存空間的類,都屬于“值類”。
注意:有一種“值類”不需要覆蓋equals方法,那就是單例。也就是說(shuō),如果一個(gè)類,它又是單例又是“值類”的話,它就不需要覆蓋equals方法。

4. 在覆蓋equals方法時(shí)我們需要遵行的規(guī)范

(1)自反性:
即對(duì)于一個(gè)非空對(duì)象x,x.equals(x)必須返回true。

(2)對(duì)稱性:
即對(duì)于非空的對(duì)象x、y,如果x.equals(y)返回true的話,則y.equals(x)則必須返回true。

(3)傳遞性:
即對(duì)于非空的對(duì)象x、y、z,如果x.equals(y)返回true,y.equals(z)返回true,則x.eqauls(z)則必須返回true。

(4)一致性:
即對(duì)于非空對(duì)象x,y,只要equals方法的中比較的字段沒(méi)有被修改,那么x.equals(y)不管執(zhí)行多少次都是返回true,或都是返回false。

(5)和null相比必須返回false:
即對(duì)于非空對(duì)象x,x.equals(null)必須返回false;

5. 實(shí)現(xiàn)高質(zhì)量equals方法的訣竅

(1)用==操作符來(lái)檢查“參數(shù)是否是這個(gè)對(duì)象的引用”。如果是,則返回true。
這樣做是為了提高性能。

(2)使用instanceof操作符來(lái)檢查“參數(shù)是否為真確類型”。如果不是,則返回false。
“正確類型”一般指的是equals方法所在的類。有些情況是指該類所實(shí)現(xiàn)的某個(gè)接口。

(3)把參數(shù)轉(zhuǎn)化為真確的類型。
在被instanceof檢測(cè)過(guò)后,我們就將Object強(qiáng)行轉(zhuǎn)換成上面所提到的“正確的類型”,instanceof保證了我們轉(zhuǎn)換的真確性。

(4)對(duì)于該類中的每個(gè)關(guān)鍵域(字段),檢查參數(shù)中的域是否與該對(duì)象中所對(duì)應(yīng)的域想匹配。
強(qiáng)轉(zhuǎn)之后,就可以開(kāi)始匹配兩個(gè)對(duì)象中的字段了。如果匹配成功就可以返回true,如果“正確的類型”是一個(gè)接口,那么需要接口提供方法來(lái)訪問(wèn)這些字段,如果是個(gè)類的話,那就不用說(shuō)了。
字段匹配技巧:

a、如果是非float和double類型的基本數(shù)據(jù)類型,那么直接使用==符號(hào)。

b、如果是float和double,則使用Float.compare和Double.compare方法。

c、其他類型(也就是那些需要new出對(duì)象的類)則調(diào)用他們自身的equals方法。有些字段可能被允許為空,所以要進(jìn)行判斷,如下:

field == null ?  o.field == null : filed.equal(0.field);

d、數(shù)組的話需要遍歷每一個(gè)元素進(jìn)行匹配,匹配的時(shí)候參考上面的三條方法。

6. 覆蓋equals方法的時(shí)候我們還需要注意的地方

(1) 覆蓋equals的時(shí)候總是要覆蓋hashCode方法。(為什么覆蓋和怎么覆蓋會(huì)在下一篇文章講)
(2) 不要企圖讓equals方法過(guò)于智能。只是匹配對(duì)象的類型和對(duì)象中的各個(gè)參數(shù)的話很容易做到,并且一般不會(huì)違反上面提到的規(guī)范。如果你過(guò)度的去尋求各種等價(jià)關(guān)系,那么上面的約定將很難遵守。
(4)覆蓋equals方法的時(shí)候請(qǐng)?jiān)诜椒ㄇ懊婕?code>@Override注解。

本文到此結(jié)束

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容