1、解釋
我們知道,Object類提供了equals方法:
public boolean equals(Object obj) {
return (this == obj);
}
實現了對象地址的比較。也就是判斷是否指向了同一對象。下列情況下,我們需要覆蓋equals方法:
- 當需要判斷是否邏輯相等,且超類還沒有覆蓋equals
這通常屬於“值類”(value class)的情形。值類僅僅是一個表示值的類,例如Integer或者String 。程序員在利用equals方法來比較值對象的引用時,希望知道它們在邏輯上是否相等,而不是想了解它們是否指向同一個對象。String和八大基本類型的封裝類都已經覆蓋了equals方法。
在覆蓋equals 方法的時候,必須要遵守它的通用約定:
- 自反性(reflexive):對於任何非null的引用值x,x.equals(x)必須返回true
- 對稱性(symmetric):對於任何非null的引用值x和y,當且僅當y.equals(x)返回true時,x.equals(y)必須返回true
- 傳遞性(transitive):對於任何非null的引用值x、y和z,如果x.equals(y)為true,並且y.equals(z)也返回true,那麼x.equals(z)也必須返回true
- 一致性(consistent):對於任何非null的引用值x和y,只要equals的比較操作在對象中所用的信息沒有被修改,多次調用x.equals(y)就會一致地返回true,或者一致地返回false
- 非空性(Non-nullity):對於任何非null的引用值, x.equals(null)必須返回false
2、實現高質量equals的方法
- 使用==操作符檢查"參數是否為這個對象的引用"
- 使用instanceof操作符檢查"參數是否為正確的類型"
- 對於類中的關鍵屬性,檢查參數傳入對象的屬性是否與之相匹配
- 編寫完equals方法後,問自己它是否滿足對稱性、傳遞性、一致性
- 重寫equals時總是要重寫hashCode
- 不要將equals方法參數中的Object對象替換為其他的類型,在重寫時不要忘掉@Override註解
3、最佳實踐
在實際工作中,覆蓋equals方法比較麻煩,通常我們使用IDE工具自帶的生成equals功能:
private String loginId;
private String password;
private String name;
例如有以上屬性的value object,使用工具生成的代碼如下:
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ExampleBean other = (ExampleBean) obj;
if (loginId == null) {
if (other.loginId != null)
return false;
} else if (!loginId.equals(other.loginId))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (password == null) {
if (other.password != null)
return false;
} else if (!password.equals(other.password))
return false;
return true;
}
專業從事軟件研發工作多年,在軟件設計、開發、測試、研發管理等領域裡經驗豐富,感興趣的朋友可以關注我的頭條號,相信一定會有所收穫。
如果有軟件研發方面的問題,可以諮詢我。
謝謝!
閱讀更多 IT極客老兵 的文章