覆盖equals方法与创建新方法

时间:2008-08-19 17:05:27

标签: java oop

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

支持和反对覆盖equals方法的理由是什么?

7 个答案:

答案 0 :(得分:19)

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

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

  

如果两个物体相等   然后是equals(Object)方法   在每个上调用hashCode方法   两个对象必须产生相同的   整数结果。

编辑:我没有将此作为完整答案发布,因此我将回应Fredrik Kalseth的声明,即覆盖等于最适合immutable objects。引用Map的API:

  

注意:如果,必须非常小心   可变对象用作映射键。   未指定地图的行为   如果对象的值发生了变化   以一种影响平等的方式   比较,而对象是一个关键   在地图上。

答案 1 :(得分:8)

我强烈建议您选择有效Java的副本并阅读第7项,并遵守equals contract。如果要覆盖可变对象的equals,则需要小心,因为许多集合(如Maps和Sets)使用equals来确定等效性,并且变异集合中包含的对象可能会导致意外结果。 Brian Goetz还有一个非常好的overview of implementing equals and hashCode

答案 2 :(得分:4)

你应该“绝不”覆盖等于&可变对象的getHashCode - 这适用于.net和Java。如果你这样做,并且使用这样的对象作为f.ex中的键字典然后更改该对象,那么你将遇到麻烦,因为字典依赖于哈希码来查找对象。 / p>

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

答案 3 :(得分:2)

@David Schlosnagle mentions提到了Josh Bloch的Effective Java - 对于任何Java开发人员来说,这都是必读

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

  

通常情况如此,但并非严格要求(compare(x,y)== 0)==(x.equals(y))。一般来说,任何违反此条件的比较器都应清楚地表明这一事实。推荐的语言是“注意:这个比较器强加了与equals不一致的排序。”

答案 4 :(得分:0)

Equals方法用于比较参考。所以不应该改变它的行为。

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

答案 5 :(得分:0)

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

当你这样做时,你也应该覆盖hashCode()

有关完整说明,请参阅here

答案 6 :(得分:0)

老实说,在Java中,没有真正反对覆盖 equals 的论据。如果你需要比较实例的相等性,那就是你要做的。

如上所述,您需要了解与 hashCode 的合同,同样,请注意Comparable界面周围的问题 - 几乎在所有情况下您都希望< em>自然排序由Comparable定义为与equals 一致(参见规范计数器示例的BigDecimal api doc)

除了不使用现有的库类之外,创建一个决定相等性的新方法,在某种程度上面对Java约定。