在Java中重写equals - getClass()方法

问题描述:

在文章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

您只需要看看java.util就可以看到.equals()被重新定义为仅关注接口的示例。例如,java.util.List,其中定义了相关的特征相等性,并明确记录了计算散列码的公式。

所以要回答你的问题,是的 - 忽略子类型在某些情况下是有意义的。但是我喜欢Josh Bloch通过将接口作为等价方面的方法。

情况并非一定如此。例如,如果您查看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)); 
}