Java 用compareTo实现equals方法

Java 用compareTo实现equals方法,java,equals,compareto,Java,Equals,Compareto,一般问题:在Java中实现对默认equals方法的重写时,简单地使用已经实现的compareTo方法与将独立逻辑写入equals方法相比,我应该考虑什么?我注意到有人在另一个问题中提到,foo.equals((String)null)返回false,而String.compareTo((String)null)抛出一个NullPointerException。是什么使这些不一致的结果成为理想的功能 示例等于方法: @Override public boolean equals(Object ob

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

示例
等于
方法:

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

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

编辑:

在进一步审查之后,我发现值得注意的是,文件还说明了以下内容:

实现者必须确保所有x和y的sgn(x.compareTo(y))==-sgn(y.compareTo(x))。(这意味着x.compareTo(y)必须在y.compareTo(x)引发异常时引发异常。)

因此,由于
null.compareTo(x)
显然会抛出一个,因此
x.compareTo(null)
也应该抛出一个NPE。而对于平等者,情况未必如此。我非常重视NPE的正确处理,因此我觉得这一点相对重要。

compareTo
可能需要做更多的工作,而不仅仅是为了得到一个平等的答案,这可能最终会成为一个性能问题,具体取决于您的应用程序使用情况


除此之外,遵循原则,最好按照您的建议重新使用代码。

compareTo()
之间的区别在于
equals()
只检查
compareTo()中的两个对象是否相等
用于标识指定类实例的自然顺序。另外,
equals()
方法与
hashCode()
方法有契约,但
compareTo()
没有

根据:

注意null不是任何类的实例,e.compareTo(null) 即使e.equals(null)返回,也应引发NullPointerException 错

强烈建议,但并非严格要求: (x.与(y)==0)==(x.等于(y))。一般来说,任何阶级 实现可比较接口并违反此条件的 应该清楚地表明这一事实。建议使用的语言为“注意: 此类具有与equals不一致的自然顺序。”

您可以在
equals()
方法中随意重用
compareTo()
方法逻辑,但请记住
equals()
hashCode()
和来自JavaDoc的
compareTo()
方法的所有契约。如果它们之间没有冲突,那就继续吧


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

请注意,理想情况下,
.compareTo()
应与
.equals()
保持一致,但这绝不是保证。例如,请参见
BigDecimal
。是的,
null
如果您选择该路径,则处理可能是一个问题。
Double.NaN
对于
等于(对象)
比较(Double)
都有令人惊讶的行为
NaN.equals(NaN)
true
,但
NaN==NaN
false
。类似地,
NaN
compareTo
调用中最大的
Double
,并且
NaN.compareTo(NaN)==0
equals
compareTo
一致,但在这种情况下,
Double
对象不符合IEEE标准。必要但令人惊讶。“我认为契约的执行更重要。”虽然性能始终是一个值得关注的问题,但从长远来看,契约的执行似乎可以避免我编写更多的测试用例。谢谢我把我变成了那个小金块。关于潜在表现的好消息。尽管我对NPE大肆吹嘘,但我忽略了我提出的代码已经正确地处理了它们,假设它们在比较中做得很好。剩下的唯一问题是性能。