比较Java中的双精度会产生奇怪的结果

Sim*_*eon 13 java double autoboxing equals

我真的无法理解为什么会发生以下情况:

Double d = 0.0;
System.out.println(d == 0); // is true
System.out.println(d.equals(0)); // is false ?!
Run Code Online (Sandbox Code Playgroud)

然而,这可以按预期工作:

Double d = 0.0;
System.out.println(d == 0.0); // true
System.out.println(d.equals(0.0)); // true
Run Code Online (Sandbox Code Playgroud)

我很肯定这与某种方式的自动装箱有关,但我真的不知道为什么0在使用==操作符和.equals调用时会有不同的方法.

这不是暗示违反equals合同吗?

  *  It is reflexive: for any non-null reference value
  *     x, x.equals(x) should return
  *     true.

编辑:

谢谢你的快速答案.我认为它的盒装方式不同,真正的问题是:它为什么装箱不同?我的意思是,这将是更直观,如果d == 0d不是d.equals(0d)非常直观和预期,但是如果d == 0它看起来像一个Integertrue不是"直觉" d.equals(0)也应该是真实的.

Jig*_*shi 19

只需将其更改为

System.out.println(d.equals(0d)); // is false ?! now true
Run Code Online (Sandbox Code Playgroud)

你将double与Integer0 进行比较

在封面下

System.out.println(d.equals(0)); // is false ?!
Run Code Online (Sandbox Code Playgroud)

0将被自动装箱,Integer并将Integer的一个实例传递给类的equals()方法Double,它将在那里进行比较

@Override
    public boolean equals(Object object) {
        return (object == this)
                || (object instanceof Double)
                && (doubleToLongBits(this.value) == doubleToLongBits(((Double) object).value));
    }
Run Code Online (Sandbox Code Playgroud)

当然会返回虚假.

更新

当你使用==它做比较时比较值,所以不需要autobox,它直接操作值.凡equals()接受Object,所以如果你尝试调用d1.equals(0),0没有对象,因此它会执行自动装箱,它将它收拾整数这是一个对象.


for*_*ran 6

Number对象仅等于具有相同值的数字(如果它们属于同一类型).那是:

new Double(0).equals(new Integer(0));
new BigInteger("0").equals(new BigDecimal("0"));
Run Code Online (Sandbox Code Playgroud)

和类似的组合都是假的.

在您的情况下,文字0被装入一个Integer对象.


due*_*l0r 5

可能值得注意的是,您应该像这样比较浮点数:

|x - y| < ?, ? very small
Run Code Online (Sandbox Code Playgroud)