12

一般问题:在 Java 中实现默认equals方法的覆盖时,我应该对简单地使用已经实现compareTo的方法而不是在 equals 方法中编写独立的逻辑有什么顾虑?我注意到有人在另一个问题中提到foo.equals((String)null)返回 false 而String.compareTo((String)null)抛出NullPointerException. 是什么让这些不一致的结果成为理想的功能?

样品equals方法:

@Override
public boolean equals(Object obj) {
    if (obj != null && obj instanceof MyClass) {
        MyClass msg = (MyClass)obj;
        return this.compareTo(msg) == 0;
    }
    return false;
}

编辑: 引用自Comparable的文档

当且仅当 e1.compareTo(e2) == 0 对于类 C 的每个 e1 和 e2 具有与 e1.equals(e2) 相同的布尔值时,类 C 的自然排序被称为与 equals 一致。注意null 不是任何类的实例,即使 e.equals(null) 返回 false,e.compareTo(null) 也应该抛出 NullPointerException

编辑:

经过进一步审查,我发现Comparable文档还指出以下内容:

实现者必须确保所有 x 和 y 的 sgn(x.compareTo(y)) == -sgn(y.compareTo(x))。(这意味着如果 y.compareTo(x) 抛出异常,则 x.compareTo(y) 必须抛出异常。)

因此,由于null.compareTo(x)显然会抛出NPEx.compareTo(null)因此也应该抛出 NPE 。而对于equals,情况不一定如此。我对正确处理 NPE 非常重视,所以我觉得这相对重要。

4

2 回答 2

9

compareTo 可能涉及比获得相等答案所需的更多工作,这可能最终成为性能问题,具体取决于您的应用程序使用情况。

除此之外,遵循DRY原则,按照您的建议重用代码将是一个好主意。

于 2013-05-29T14:40:40.007 回答
6

equals()和之间的区别在于compareTo()equals()它只检查两个对象是否相等,其中compareTo()用于识别指定类实例的自然顺序。方法也equals()与方法有合同,hashCode()compareTo()没有。

根据JavaDoc

请注意,null 不是任何类的实例,即使 e.equals(null) 返回 false,e.compareTo(null) 也应该抛出 NullPointerException。

强烈建议但不严格要求 (x.compareTo(y)==0) == (x.equals(y))。一般来说,任何实现了 Comparable 接口并违反此条件的类都应该清楚地表明这一事实。推荐的语言是“注意:这个类有一个与equals不一致的自然顺序。”

您可以随意compareTo()在您的方法中重用方法逻辑,equals()但请记住所有与equals(),hashCode()和 JavaDoc 中的compareTo()方法的契约。如果他们不相互冲突,那么继续。

我认为合同的执行是更重要的一点。

于 2013-05-29T15:04:30.347 回答