在帖子What issues should be considered when overriding equals and hashCode in Java?中,我们详细解释了如何使用getClass在Java中编写适当的相等方法来比较我们所等的两个对象的RUntime类型。我理解我们这样做的原因是为了确保如果B延伸A我们想要a.equals(b)= b.equals(a)(反身性)。
它确实提供了一个很大的局限性。如果你有一个对象集合A,那么它们是A的子类,那么a.equals(b)总是假的......或许,在某些时候,我们应该坚持旧的{{1}运算符提供多态性并允许子类型相等?你的想法是什么?
答案 0 :(得分:4)
您只需要查看java.util
即可查看重新定义.equals()
的地方的示例,仅关注界面。例如,java.util.List
,其中定义了相关的特征相等性,并且明确记录了计算哈希码的公式。
所以回答你的问题,是的 - 在某些情况下忽略子类型是有道理的。但我喜欢Josh Bloch通过使接口成为等价方面的方法。
答案 1 :(得分:1)
情况不一定如此。例如,如果查看JDK中的集合,它们会使用较不严格的相等定义。下面的代码输出“true”两次。最后,这是合同和文件的问题。
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));
}