2

在帖子中,在 Java 中覆盖 equals 和 hashCode 时应该考虑哪些问题?其中一个非常详细地解释了如何在 Java 中使用 getClass 编写适当的相等方法来比较我们相等的两个对象的运行时类型。我知道我们这样做的原因是确保如果 B 扩展 A 我们想要 a.equals(b) = b.equals(a) (自反性)。

在我看来,它确实提供了一个很大的限制。如果你有一个对象 A 的集合,插入几个 B 对象,因为它们是 A 的子类,那么 a.equals(b) 总是错误的......也许,在某些时候,我们应该坚持使用旧的instanceof运算符来提供多态性并允许子类型的平等?你怎么认为?

4

2 回答 2

4

您只需要查看如何重新定义以仅关心接口java.util的示例。.equals()例如,java.util.List,其中定义了相关特征相等性,并且明确记录了计算哈希码的公式。

所以回答你的问题,是的——在某些情况下忽略子类型是有意义的。但我喜欢 Josh Bloch 的方法,即让接口成为等价的方面。

于 2012-08-06T15:31:08.917 回答
1

不一定是这样。例如,如果您查看 JDK 中的集合,它们会使用不那么严格的相等定义。下面的代码两次输出“true”。最后,这是合同和文件的问题。

equalsList 中的合同(重点是我的):

比较指定对象与此列表是否相等。当且仅当指定对象也是一个列表时返回 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));
}
于 2012-08-06T15:31:42.240 回答