基礎 | 重寫equals方法
參加VIVO秋招面試中,在回答「Object類有哪些方法?每個方法分別有什麼作用?」問題時,提到equals()方法,就又被問到 「在重寫equals()方法需要注意什麼?」,頓時就一臉懵逼,這也是面試「Java開發工程師」過程中的高頻問題,在此進行一個系統的總結與梳理。
參考答案
為什麼要重寫equals()方法?
Object類中equals()方法的預設實現主要是用於判斷兩個物件的引用是否相同。而在實際開發過程中,通常需要比較兩個物件的對應屬性是否完全相同,故需要重寫equals()方法。
如何重寫equals()方法?
假設equals()方法的形參名為otherObj,稍後需要將其轉換為另一個叫做other的變數。
第一步,檢測this與otherObj是否引用同一物件:
if(this == otherObject) return true;
第二步,檢測otherObj是否為空:
if(otherObject == null) return false;
第三步,判斷this與otherObj是否屬於同一個類,具體分兩種情況:
(1). 如果equals()方法的語義在每個子類中均有所改變,則使用getClass()方法進行檢測:
if(getClass() != otherObject.getClass()) return false;
(2). 如果equals()方法在所有子類中均有統一的語義,則使用instanceof關鍵字進行檢測:
if (!(otherObject instanceof ClassName)) return false;
第四步,將otherObj轉換為相應類的型別變數:
ClassName other = (ClassName) otherObject;
第五步,對所有需要比較的域進行一一比較,若全匹配則返回true,否則返回false。
關於equals()語義的補充說明:假設現有Employee與Manager兩個類,Manager類繼承Employee類。若僅將ID作為相等的檢測標準,則僅用在Employee類中重寫equals()方法,並將該方法宣告為final的即可,這就是所謂的「擁有統一的語義」。
重寫equals()方法需要注意什麼?
歸根結底,還是想問equals()方法的主要特性。Java語言規範要求equals()方法具有如下特性:
- 自反性:對於任何非空引用x,x.equals(x)應該返回true。
- 對稱性:對於任何引用x和y,當且僅當y.equals(x) 返回true時,x.equals(y)也應該返回true。
- 傳遞性:對於任何引用x、y和z,如果x.equals(y) 返回true,y.equals(z)返回true,x.equals(z)也應該返回true。
- 一致性:如果x和y引用的物件沒有發生變化,反覆呼叫x.equals(y)應該返回同樣的結果。
- 非空性:對於任何非空引用x,x.equals(null)應該返回false。
原始碼閱讀
// Object類中equals()方法的預設實現
public boolean equals(Object obj) {
return (this == obj);
}
// String類中equals()方法的具體實現
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
// 具有統一語義
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
推薦閱讀
歡迎關注
Java名企面試吧,每天10點24分,我們不見不散!
丙子先生的宗旨是,每天以短篇幅講高頻面試題,不增加太多負擔,但需要持之以恆。
能力有限,歡迎指教!