-
Object類默認的equals()方法
比較的是什么?
Object類的equals()方法比較的是兩個對象對象的引用,而不比較兩個對象的狀態。
-
自定義的equals()方法
為什么要自定義(覆蓋超類Object)equals()方法?
因為默認的equals比較的是對象的引用,而實際更多比較的是對象的狀態是否相等。
public boolean equals(Object otherObject)
{
// 比較引用
if (this == otherObject) return true;
// 判斷對象是否為空
if (otherObject == null) return false;
// 類型不相同則必然不同,且為下面強制類型轉換做準備
if (getClass() != otherObject.getClass()) return false;
// 強制類型轉換
Employee other = (Employee) otherObject;
// 判斷域
return Objects.equals(name, other.name)
&& salary == other.salary
&& Objects.equals(hireDay, other.hireDay);
}
以上比較域為什么不直接使用name.equals(other.name)?
有可能name == null;
使用Object.euqal(a,b):
- 若a、b都是null,則返回true;
- 若a、b其一是null,則返回false;
- 否則調用a.equals(b)。
子類覆蓋equals()方法
如果子類定義equals()方法,則先調用超類的equals()方法,若返回false,則不相同,不需要比較子類的實例域。
public boolean equals(Object otherObject){
if (!super.equals(otherObject)) return false;
//超類的getClass()方法比較的是實際類型,因此可以確定是否可以進行強制類型轉換
Manager other = (Manager) otherObject;
return bonus == other.bonus;
}
- getClass()和instanceof比較對象類型
如果子類能夠擁有自己相等的概念,則對稱性強制要求用getClass();
如果由超類決定相等概念,則用instanceof檢查類,這樣可以在不同子類對象之間比較相等,僅實例域。
-
散列碼HashCode
未定義hashCode方法的情況下,每個對象都有其默認的散列碼,其值表示對象的地址。
字符串的hashCode
字符串的hashCode方法已定義,字符串散列碼是由內容導出,內容相同則hashCode相同;
StringBuffer的hashCode未定義,因此hashCode是對象的地址,即使字符串內容相同,hashCode也不同。
重新定義equals就必須重新定義hashCode
一是為了方便用戶可以將對象插入到散列表中;
二是equals返回true,則兩個對象的hashCode必須相同。(例如定義Employee的equals方法比較的是雇員ID,則hashCode方法就要返回雇員ID的散列碼,而不是姓名等的存儲地址)
定義的equals()方法和hashCode()方法
public boolean equals(Object otherObject){
if (this == otherObject) return true;
if (otherObject == null) return false;
if (getClass() != otherObject.getClass()) return false;
Employee other = (Employee) otherObject;
return Objects.equals(name, other.name)
&& salary == other.salary
&& Objects.equals(hireDay, other.hireDay);
}
public int hashCode(){
return Objects.hash(name, salary, hireDay);
}
- 數組域的散列碼可以用靜態的Arrays.hashCode方法計算由一個數組元素散列碼組成的散列碼。