为什么Double.NaN在包装在Double实例中时自相同?

Chr*_*urt 11 java

这个问题我学到了Double.NaN不等于它自己.

我正在为自己验证这一点,并注意到如果你在Double实例中包装Double.NaN则不是这种情况.例如:

public class DoubleNaNTest {
    public static void main(String[] args) {
        double primitive = Double.NaN;
        Double object = new Double(primitive);

        // test 1 - is the primitive is equal to itself?
        boolean test1 = primitive == primitive;

        // test 2 - is the object equal to itself?
        boolean test2 = object.equals(object);

        // test 3 - is the double value of the object equal to itself?
        boolean test3 = object.doubleValue() == object.doubleValue();

        System.out.println("Test 1 = " + test1);
        System.out.println("Test 2 = " + test2);
        System.out.println("Test 3 = " + test3);
    }
}
Run Code Online (Sandbox Code Playgroud)

输出:

Test 1 = false
Test 2 = true
Test 3 = false
Run Code Online (Sandbox Code Playgroud)

在我看来,所有三个测试都应该评估为false,因为所有三个操作都是等效的(因为如果你使用Double.NaN之外的其他东西).

有人能解释一下这里发生了什么吗?

Ste*_*n C 11

发生的事情是该equals方法故意偏离IEE浮点.从Javadoc引用java.lang.Doubleequals(Object)方法.

但是,有两个例外:

  • 如果d1和d2都表示Double.NaN,则equals方法返回true,即使Double.NaN == Double.NaN的值为false.
  • 如果d1表示+0.0而d2表示-0.0,反之亦然,则
    等值测试的值为false,即使
    +0.0 == - 0.0的值为true.

此定义允许哈希表正常运行.

结果是,如果您想要100%IEE浮点兼容性,则需要显式取消java.lang.Double实例化实例并比较结果double值.


Dig*_*oss 5

这样哈希表就可以了

他们故意偏离IEEE方式,因此哈希表可以工作.

您可以在api文档中获取部分故事.故事的其余部分是:每个继承自Object的类(都是它们)都有一个维护Object不变量的契约.合同的存在使得库的其余部分可以实现所有这些好的集合和事物.没有什么可以阻止你破坏它,但是你不能确定那些使用Object的东西会起作用.