关于Java:覆盖equals方法与创建新方法

关于Java:覆盖equals方法与创建新方法

Overriding the equals method vs creating a new method

我一直认为应该重写Java中的.equals()方法,使其特定于您创建的类。 换句话说,要寻找两个不同实例的等效性,而不是对同一实例的两个引用。 但是,我遇到了其他程序员,他们似乎认为默认对象的行为应该保留下来,并创建一个新方法来测试同一类的两个对象的等效性。

支持和反对覆盖equals方法的论点是什么?


如果要在标准库类中测试等效性,则必须重写equals方法(例如,确保java.util.Set包含唯一元素或将对象用作java.util.Map对象中的键)。

请注意,如果您覆盖等号,请确保遵守文档中所述的API合同。例如,确保您还重写Object.hashCode:

If two objects are equal according to
the equals(Object) method, then
calling the hashCode method on each of
the two objects must produce the same
integer result.

编辑:我没有将其发布为关于该主题的完整答案,因此,我将回应弗雷德里克·卡尔塞斯(Fredrik Kalseth)的说法,即重写等于最适合不可变对象。引用Map API:

Note: great care must be exercised if
mutable objects are used as map keys.
The behavior of a map is not specified
if the value of an object is changed
in a manner that affects equals
comparisons while the object is a key
in the map.


我强烈建议您选择《有效Java》的副本,并遵循平等合同通读第7项。如果要覆盖可变对象的相等值,则需要小心,因为诸如Maps和Sets之类的许多集合都使用相等值来确定等效性,并且对集合中包含的对象进行变异可能会导致意外结果。 Brian Goetz还对实现equals和hashCode进行了很好的概述。


对于可变对象,您不应"永远"覆盖equals和getHashCode-这适用于.net和Java。如果这样做,并在f.ex字典中使用此类对象作为键,然后更改该对象,则会遇到麻烦,因为字典依赖哈希码来查找对象。

这是一篇有关该主题的好文章:http://weblogs.asp.net/bleroy/archive/2004/12/15/316601.aspx


@David Schlosnagle提到了乔什·布洛赫(Josh Bloch)的《有效的Java》-这是任何Java开发人员都必须读的书。

有一个相关的问题:对于不可变的值对象,您还应该考虑覆盖compare_to。如果它们不同,则标准措辞在Comparable API中:

It is generally the case, but not strictly required that (compare(x, y)==0) == (x.equals(y)). Generally speaking, any comparator that violates this condition should clearly indicate this fact. The recommended language is"Note: this comparator imposes orderings that are inconsistent with equals."


老实说,在Java中并没有真正反对覆盖相等的论点。如果您需要比较实例是否相等,那就是您要做的。

如上所述,您需要了解与hashCode的约定,并且类似地,请注意Comparable接口周围的陷阱-在几乎所有情况下,您都希望由Comparable定义的自然顺序与equals保持一致(请参阅BigDecimal api doc(用于规范计数器示例)

除了不使用现有的库类之外,创建一种用于确定相等性的新方法还需要面对Java约定。


如果在将对象添加到排序的数据结构(SortedSet等)中时想要特定的行为,则只需要覆盖equals()方法。

这样做时,您还应该覆盖hashCode()

请参阅此处以获取完整说明。


Equals方法旨在比较引用。因此,不应改变它来更改其行为。

如果需要,您应该创建一个新方法来测试不同实例中的等效性(或在某些.NET类中使用CompareTo方法)


推荐阅读