Effective Java代碼規則之十:覆蓋equals時請遵守通用約定

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;
}
Effective Java代碼規則之十:覆蓋equals時請遵守通用約定

專業從事軟件研發工作多年,在軟件設計、開發、測試、研發管理等領域裡經驗豐富,感興趣的朋友可以關注我的頭條號,相信一定會有所收穫。

如果有軟件研發方面的問題,可以諮詢我。

謝謝!


分享到:


相關文章: