【问题标题】:Overriding the equals method vs creating a new method覆盖equals方法与创建新方法
【发布时间】:2010-09-06 04:54:09
【问题描述】:

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

支持和反对重写 equals 方法的论据是什么?

【问题讨论】:

    标签: java oop


    【解决方案1】:

    Equals 方法旨在比较引用。所以不应该重写它来改变它的行为。

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

    【讨论】:

      【解决方案2】:

      如果您想测试标准库类中的等价性(例如,确保 java.util.Set 包含唯一元素或使用对象作为 java.util.Map 对象中的键),则需要重写 equals 方法。

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

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

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

      注意:如果出现以下情况,必须非常小心 可变对象用作映射键。 未指定地图的行为 如果一个对象的值改变了 以影响平等的方式 对象是键时的比较 在地图中。

      【讨论】:

      【解决方案3】:

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

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

      完整说明请参见here

      【讨论】:

        【解决方案4】:

        我强烈建议拿起一本 Effective Java 并阅读第 7 条,遵守equals contract。如果您为可变对象覆盖 equals,则需要小心,因为许多集合(例如 Maps 和 Sets)使用 equals 来确定等价,并且更改集合中包含的对象可能会导致意外结果。 Brian Goetz 也有一个不错的overview of implementing equals and hashCode

        【讨论】:

          【解决方案5】:

          对于可变对象,您应该“永远不要”覆盖 equals 和 getHashCode - 这适用于 .net 和 Java。如果你这样做了,并使用这样的对象作为 f.ex 字典中的键,然后 change 该对象,你就会遇到麻烦,因为字典依赖于哈希码来查找对象。

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

          【讨论】:

            【解决方案6】:

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

            如上所述,您需要了解与 hashCode 的约定,同样,请注意 Comparable 接口周围的陷阱 - 在几乎所有情况下您都需要 由 Comparable 定义的自然排序与等于一致(有关规范的反示例,请参阅BigDecimal api 文档)

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

            【讨论】:

              【解决方案7】:

              @David Schlosnagle mentions 提到了 Josh Bloch 的 Effective Java -- 这是任何 Java 开发人员的必读

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

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

              【讨论】:

                猜你喜欢
                • 2014-05-27
                • 2020-01-30
                • 2011-04-17
                • 1970-01-01
                • 1970-01-01
                • 2015-02-25
                • 2011-02-02
                • 1970-01-01
                • 2010-09-16
                相关资源
                最近更新 更多