一般问题:在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文档中引用:
类C的自然排序被认为是与等于一致的,当且仅当对于类C的每个e1和e2,e1.compareTo(e2) == 0具有与e1.equals(e2)相同的布尔值。请注意,空值不是任何类的实例,即使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)
明显会抛出NPE,所以x.compareTo(null)
也应该抛出NPE。而对于equals方法,情况并非总是如此。我非常注重NPE的正确处理,因此我认为这相当重要。
.compareTo()
应该与.equals()
一致,但这绝非保证。例如,可以参考BigDecimal
类。是的,如果你选择使用null
处理,可能会遇到问题。 - fgeDouble.NaN
对于equals(Object)
和compareTo(Double)
都有令人惊讶的行为。NaN.equals(NaN)
是true
,但NaN == NaN
是false
。同样地,在compareTo
调用中NaN
是最大的Double
,且NaN.compareTo(NaN) == 0
。equals
与compareTo
一致,但在这种情况下,Double
对象不遵循IEEE标准。必要,但令人惊讶。 - Eric Jablow