淺談Java中的equals方法和==
本質區別
==
==
是用於比較對象在內存中的地址的。由於Java中的變量大多都是引用變量(也就是指針),所以只有當兩個變量指向同一實例化的對象時,用==
才能返回true。
equals方法
equals方法則是通過該類中設計好的方法來判斷兩個比較的對象是否滿足判等條件。例如String類中,設計的方法就是:比較每個字母,如果都一樣就返回true。
對比
比如我們實例化了兩個對象—>人,而且他們年齡和性別都一樣。 但是他們在內存中的地址是不一樣的。所以當使用==
判斷時,返回的值是false。但是如果設計一個equals方法,表明如果年齡一樣就返回true,那麼通過equals方法返回的值就是true。因爲在實際問題中對於判等的需求不同,設計方法也不同。(比如設計一個員工類,只要員工ID一樣就可以返回true一樣)。
equals方法的設計原則
滿足等價關係
等價關係有三點要求:
1.對稱性:若x.equals(y) 返回true, 那麼 y.equals(x) 也應當返回true。
2.自反性:對於任何非空的x,x.equals(x) 應當恆返回true。
3.傳遞性: 若x.equals(y) 返回true, y.equals(z) 返回true,那麼x.equals(z)也應當返回true。
也就是說,equals返回true的前提是建立在類相同,對比目標相同的情況下的。所以在設計的時候還要先檢查類型是否相同
!
但是對於第一點:對稱性,可能你會想到,有些情況下如果要對比父類和子類該怎麼辦?
如果嚴格按照等價關係來講,只有類完全相同才能對比。如果x是父類,y是子類。在比較時,當y.equals(x)返回true時,x.equals(y)不一定成功(因爲子類可以有父類的,但是對比時,父類不一定有子類的),這樣不能滿足對稱性,所以理論上是不好的
但也可以結合實際問題變通
設想這樣一個場景:
有一個公司,有很多Employee,也有Manager。Manager也是僱員,所以Manager當然也是Employee的子類了。在公司裏,每個員工都有自己獨特的ID,這就意味着我們可以直接通過ID來判斷兩個員工是不是同一個人了。不過這裏就與上文的對稱性產生了衝突。但是實際情況實際考慮,這裏在設計的時候就可以設計成如果是繼承關係的類,也可以比較
這裏可以用到instanceof
關鍵詞:
A instance of B
A是不是B的實例(A可以是B的子類或者同類)
當然,這種最好結合實際情況提前設計好唄。
代碼
示列
以下是一個嚴格遵循等價關係的equals方法的寫法:
public boolean equals(Object other)
{
//這只是個優化,如果都是一個地址了必定一樣了。
if(this==other)
return true;
//檢測是否爲空,否則下一步會報錯的
if(other==null)
return false;
//檢測類型是否完全一樣
if(getClass()!=other.getClass())
return false;
//如果你要想父類子類比較
//if(other instanceof this !=true)
// return false;
//確定了類型一樣了,可以正式開始比較了
Employee employee = (Employee)otherObject;
//name是string類型,用String類型內已經寫好了的euqals比較即可
//salary是int類型,是基本類型所以可以直接用==
return name.equals(other.name) && salary==other.salary
}
#其他注意事項
覆蓋
例如下面這一段代碼,你能找的出問題嗎(還是上面Manager和Employee的例子):
public class Manager
{
public boolean equals(Manager other)
{
return other!=null
&&this.bonus==other.bonus
&&getClass()==other.getClass()
}
//Manager特有的屬性--獎金bonus(int類型),普通Employee是沒有的
}
這個方法聲明的顯式參數類型是Manager,而我們剛纔在Employee類裏的equals方法裏聲明的是Object類的參數類型。所以說,這樣寫出來的只是個重載,並不是重寫而已。所以爲了避免錯誤類型的發生(比如編譯器傻缺偏要用Employee那個不那麼精確的比較方式),所以建議加上@Override標籤。
hashCode方法
hashCode與equals的定義必須一致,如果x.equals(y)返回true,那麼x.hashCode()與y.hashCode()也應當具有相同的值。所以在重寫了equals方法之後,最好把你在equals中對比到的屬性也在hashCode中散列了。