2012-08-06 119 views
2

在文章What issues should be considered when overriding equals and hashCode in Java?中詳細解釋瞭如何在Java中使用getClass比較兩個對象的RUntime類型(我們將其等同)來編寫適當的相等方法。我明白我們這樣做的原因是爲了確保如果B擴展A,我們需要a.equals(b)= b.equals(a)(反身性)。在Java中重寫equals - getClass()方法

它在我看來確實提供了一個很大的限制。如果你有一個對象集合A,那麼檢查一些B對象,因爲它們是A的子類,那麼a.equals(b)總是假的......也許,在某些時候,我們應該堅持舊的instanceof運營商提供多態性並允許子類型相等?你怎麼看?

+0

...是的。你說的很明顯是真的。有什麼問題? – 2012-08-06 15:41:14

+0

我沒有任何具體問題,我想知道是否有一種做法會受到青睞,以及我是否錯過了一個重要的觀點 – Bober02 2012-08-06 15:43:14

回答

4

您只需要看看java.util就可以看到.equals()被重新定義爲僅關注接口的示例。例如,java.util.List,其中定義了相關的特徵相等性,並明確記錄了計算散列碼的公式。

所以要回答你的問題,是的 - 忽略子類型在某些情況下是有意義的。但是我喜歡Josh Bloch通過將接口作爲等價方面的方法。

1

情況並非一定如此。例如,如果您查看JDK中的集合,那麼它們使用較不嚴格的等式定義。下面的代碼輸出「真」兩次。最後,這是合同和文件的問題。

equals contract in List(重點煤礦):

比較指定對象與此列表是否相等。當且僅當指定的對象也是列表時,才返回true,兩個列表具有相同的大小,並且兩個列表中的所有相應元素對都相等。 (如果(e1 == null?e2 == null:e1.equals(e2)),兩個元素e1和e2是相等的。)換句話說,如果兩個列表按照相同的順序包含相同的元素,則它們被定義爲相等。 該定義確保equals方法在List接口的不同實現之間正常工作。

注意,它只要不違反反身性要求爲所有實現List就該合同的類。

public static void main(String[] args) { 
    List<String> list1 = new ArrayList<String>(); 
    list1.add("a"); 

    List<String> list2 = new LinkedList<String>(); 
    list2.add("a"); 

    List<String> list3 = Arrays.asList("a"); 

    System.out.println("arraylist = linkedlist? " + list1.equals(list2)); 
    System.out.println("arraylist = Arrays.aslit? " + list1.equals(list3)); 
}