引自 Joshua Bloch 的 Effective Java - Second Edition
对于浮点字段,使用 Double.compare 或 Float.compare 代替关系运算符,它们在应用于浮点值时不遵守compareTo的一般约定。
它没有详细说明为什么会这样。
所以,我的问题是:
当与浮点值一起使用时,关系运算符以何种方式不遵守 compareTo 的一般约定?
引自 Joshua Bloch 的 Effective Java - Second Edition
对于浮点字段,使用 Double.compare 或 Float.compare 代替关系运算符,它们在应用于浮点值时不遵守compareTo的一般约定。
它没有详细说明为什么会这样。
所以,我的问题是:
当与浮点值一起使用时,关系运算符以何种方式不遵守 compareTo 的一般约定?
从javadoc:
public int compareTo(Double anotherDouble)
以数字方式比较两个 Double 对象。当应用于原始双精度值时,此方法执行的比较与 Java 语言数值比较运算符(<、<=、==、>=、>)执行的比较有两种不同之处:此方法考虑 Double.NaN方法等于自身并且大于所有其他双精度值(包括 Double.POSITIVE_INFINITY)。此方法认为 0.0d 大于 -0.0d。这确保了此方法强加的 Double 对象的自然排序与 equals 一致。
来自 JavaDocDouble::compareTo
以数字方式比较两个 Double 对象。当应用于原始双精度值时,此方法执行的比较与 Java 语言数值比较运算符(<、<=、==、>= >)执行的比较有两种不同之处:
此方法认为 Double.NaN 等于其自身并且大于所有其他双精度值(包括 Double.POSITIVE_INFINITY)。
此方法认为 0.0d 大于 -0.0d。
这确保了 Double.compareTo(Object)(将其行为转发给此方法)遵守 Comparable.compareTo 的一般约定,并且 Doubles 上的自然顺序与 equals 一致。
double d1 =Double.NaN;
double d2 = Double.NaN;
System.out.println(Double.valueOf(d1).equals(d2)); ---> true
System.out.println(Double.valueOf(d1).compareTo(d2)); ---> 0
System.out.println(d1 == d2); --->false
根据 [Joshua_Bloch] Effective_Java,第 3 版
本书的先前版本(第 2 版)建议 compareTo 方法使用关系运算符 < 和 > 比较整数原始字段,使用静态方法 Double.compare 和 Float.compare 比较浮点原始字段。在 Java 7 中,静态比较方法被添加到 Java 的所有盒装原始类中。在 compareTo 方法中使用关系运算符 < 和 > 很冗长且容易出错,因此不再推荐。
在 compareTo 方法的实现中比较字段值时,避免使用 < 和 > 运算符。相反,使用盒装原始类中的静态比较方法或 Comparator 接口中的比较器构造方法。