2015-01-21 30 views
28

這似乎是一個愚蠢的問題,但爲什麼我們重寫equals方法而不是使用新名稱創建新方法並使用它進行比較?爲什麼重寫equals而不是使用其他方法名稱

如果我沒有覆蓋等於這意味着==和等於檢查兩個引用是否都指向相同的內存位置?如果您使用的是依靠平等類,如HashMapHashSetArrayList等等

例如

+6

那些使用* available *'equals()'方法的數據結構呢?示例地圖,設置? – TheLostMind 2015-01-21 10:22:05

+13

你也可以用不同的名稱實現'toString()'。但是沒有其他代碼(除了你自己的)會使用它。 – Thilo 2015-01-21 10:23:25

+0

非常感謝大家:) – 2015-01-21 12:13:25

回答

57

這似乎是一個愚蠢的問題,但爲什麼我們重寫equals方法而不是使用新名稱創建新方法並使用它進行比較?

因爲所有的標準集合(ArrayListLinkedListHashSetHashMap,...)決定是否兩個對象相等時使用equals

如果你發明了一種新方法,這些集合將不知道它並且不按預期工作。

以下是非常重要的理解:如果諸如ArrayList的集合調用Object.equals,則此調用將在運行時解析爲重寫的方法。因此,即使您發明了集合不知道的類,它們仍然可以在這些類上調用方法,如equals

如果我沒有覆蓋等於意味着這兩個==和等於檢查兩個引用是否都指向相同的內存位置?

是的。 Object.equals的執行只是執行==檢查。

+0

最後一件事。如果我做了這樣的兩個字符串// String a =「Hello」;字符串b =「你好」;那意味着a和b引用都指向同一個對象?所以我可以使用equals()來隨時比較它們而不會覆蓋它?在Java中是 – 2015-01-21 11:05:51

+0

[字符串是特殊](http://stackoverflow.com/questions/513832/how-do-i-compare-strings-in-java)。如果你做'String a =「Hello」;字符串b =「你好」;'然後'=='將工作。 – aioobe 2015-01-21 11:11:31

+0

明白了,這就是爲什麼==不能用來比較兩個字符串內容:) – 2015-01-21 11:12:15

9

您覆蓋等於,如果您存儲類的元素在HashSet,你必須重寫hashCodeequals如果你想通過簡單的參考平等來確定元素的唯一性。

是的,如果您不覆蓋等於,則默認等於執行(在Object類中執行)與==相同。

4

因爲equals()Object類的一種方法,它是所有類的超類,並且由於它本身就存在於您編寫的每個類中。因此,每個集合類或其他標準類使用equals()進行對象比較。如果您希望您的自定義類對象被其他類相等支持,則必須僅覆蓋equals()(因爲其他類知道對象比較調用equals())。如果您只使用自己的類,則可以創建一個新方法,並確保所有內容都使用您的自定義方法進行比較。

2

equals和hashcode方法是特殊的方法,廣泛用於java的實用類專用集合框架和wrpper類String,Integer已經重寫了這個方法,例如如果你在HashSet中放置了任何具有正確equals和Hashcode實現的對象,爲了保持唯一性,Hashcode將與Hashset中的所有現有對象進行比較,並且如果它發現任何Hashcode匹配,進入equals方法來仔細檢查兩者是否真的相等,如果這種相等性檢查也是通過,那麼傳入的對象將被拒絕,但是如果散列碼相等性檢查沒有通過,那麼hashset將不會用於equals方法和直接放置該對象的方式進入哈希集。所以我們需要確保equals和hashcode的實現在邏輯上是正確的。

5

除了在其他答案中已經給出的主要原因之外,還要考慮程序的可讀性。

如果您覆蓋equalshashCode任何閱讀您的代碼的人都知道這些方法的用途。這樣做會告訴讀者您班級實例之間的價值平等標準。有人讀你的代碼,使用equals會立即知道你正在檢查價值相等。

如果您使用其他名稱,它只會讓讀者感到困惑,並且會花費額外的時間來閱讀JavaDocs以瞭解您的方法。

2

HashMap<T,U>這樣的類需要有一些方法來識別集合中的哪個項目(如果有的話)應該被認爲與給定項目相同。一般有兩種裝置通過此可實現:分配部分的

  1. 要求什麼被存儲在集合中必須包括虛擬方法來執行這樣的比較(並且優選地提供了一種快速方式(例如hashCode())等價類)。

  2. 要求創建集合的代碼必須提供一個對象,該對象可以接受對其他對象的引用並對它們執行與等價相關的操作。

這本來是可以省略equalshashCode()Object,並且具有類型,如HashMap僅是與該實施equatable接口,其包括這樣的構件的密鑰類型可用;希望使用由身份標識的引用集合的代碼將不得不使用IdentityHashMap。這樣的設計不會是不合理的,但是目前的設計使通用收藏集類型成爲可能,該類型使用HashMap可用於通過價值和身份進行比較的事物,而不必爲HashMap集合和IdentityHashMap集合定義一個單獨的類型。

一個替代設計可能有GeneralHashMap類型,其構造函數要求指定一個比較函數,並且IdentityHashMapHashMap都來源於該類型;後者會將其類型限制爲equatable並且其身份函數鏈與其中包含的對象的鏈相同。這種設計可能沒有什麼特別的錯誤,但那不是事情的方式。

在任何情況下,都需要一些標準手段,通過這些手段,收藏可以識別應該被視爲等效的物品;使用虛擬equals(Object)getHashCode()是一種方法。

1

問題1

有兩件事情。 equals()被比較的對象

問題2個

是當比較兩個對象使用equals()hashcode()方法位於Object類中 收集框架。但是當您使用equals()比較兩個字符串對象時,它只能檢查值。

相關問題