繁体   English   中英

为什么Collection接口有equals()和hashCode()?

[英]Why does the Collection interface have equals() and hashCode()?

为什么Collection接口有equals(Object o)hashCode() ,因为默认情况下任何实现都会有这些(继承自Object )?

集合 JavaDoc

虽然Collection接口没有对Object.equals的一般契约添加任何规定,但“直接”实现Collection接口的程序员(换句话说,创建一个是Collection但不是SetList )必须小心如果他们选择覆盖Object.equals 没有必要这样做,最简单的做法是依赖 Object 的实现,但是实现者可能希望实现一个“值比较”来代替默认的“引用比较”。 ListSet接口要求进行这样的值比较。)

Object.equals方法的一般约定规定 equals 必须是对称的(换句话说, a.equals(b)当且仅当b.equals(a) )。 List.equalsSet.equals的契约声明列表仅等于其他列表,并设置为其他集合。 因此,当将此集合与任何列表或集合进行比较时,既不实现List也不实现Set接口的集合类的自定义 equals 方法必须返回 false。 (根据相同的逻辑,不可能编写一个正确实现 Set 和 List 接口的类。)

虽然 Collection 接口没有对Object.hashCode方法的通用约定添加任何规定,但程序员应该注意,任何重写Object.equals方法的类也必须重写Object.hashCode方法以满足Object.hashCode的通用约定Object.hashCode方法。 特别是, c1.equals(c2)意味着c1.hashCode()==c2.hashCode()

回答你的具体问题:为什么它有这些方法? 这样做只是为了方便,能够包含 Java Docs,提供关于实现者应该用这些方法做什么的提示(例如比较值的相等性而不是引用)。

添加到其他很棒的答案中。 在 Collections 接口中,equals 方法在该接口中定义,以做出一些决定,使集合的两个实例相等。 来自JAVA 8 文档

更一般地说,各种集合框架接口的实现可以自由地利用底层对象方法的指定行为,只要实现者认为合适。

因此,您不会出于任何其他原因而从 Object 类中添加方法,从而为 java 文档提供更多确定性。 这就是为什么你不在接口的抽象方法中计算抽象方法中的那些方法的原因。

此外,在 JAVA 8 中,按照相同的推理思路,来自 Object 类的默认方法是不允许的,并且会产生编译错误。 我相信这样做是为了防止这种混淆。 因此,例如,如果您尝试创建一个名为 hashCode() 的默认方法,它将无法编译。

以下是Lambda FAQ中对 JAVA 8 中这种行为的更深入的解释:

接口不能为 Object 类的任何方法提供默认实现。 这是方法解析的“类获胜”规则的结果:在超类链上找到的方法总是优先于出现在任何超接口中的任何默认方法。 特别是,这意味着不能在接口内为 equals、hashCode 或 toString 提供默认实现。

考虑到某些接口实际上在文档中定义了它们的 equals 行为,这起初看起来很奇怪。 List 接口就是一个例子。 那么,为什么不允许这样做呢?

一个原因是,何时调用默认方法会变得更加难以推理。 当前的规则很简单:如果一个类实现了一个方法,那么它总是胜过默认实现。 由于接口的所有实例都是 Object 的子类,因此接口的所有实例都已经具有 equals、hashCode 和 toString 的非默认实现。 因此,接口上这些的默认版本总是无用的,它也可能无法编译。

另一个原因是在接口中提供这些方法的默认实现很可能是误导。 这些方法对对象的状态执行计算,但接口通常无法访问状态; 只有实现类可以访问此状态。 因此,类本身应该提供实现,默认方法不太可能有用。

只是为了添加上面的好答案,在这种情况下使用“equals”或“hashCode”方法是有意义的:

Collection<Whatever> list1 = getArrayList();
Collection<Whatever> list2 = getAnotherArrayList();

if(list1.equals(list2)){
    // do something
}

如果接口中没有equals方法,我们将被迫使用具体类型,这通常不是一个好习惯:

ArrayList<Whatever> list1 = getArrayList();
ArrayList<Whatever> list2 = getAnotherArrayList();

if(list1.equals(list2)){
    // do something
}

Equals和hashCode方法有助于比较对象。 集合接口对不同对象按顺序进行比较,或者按顺序检查重复项是否相等,并将使用哈希码。

Equalable&Hashable是两个默认提供的合同/规则。 通过这样做,假定为该类正确实现了给定类的equals和hashCode。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM