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

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

Double d = 0.0; System.out.println(d == 0); // is true System.out.println(d.equals(0)); // is false ?! 

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

 Double d = 0.0; System.out.println(d == 0.0); // true System.out.println(d.equals(0.0)); // true 

我很肯定这在某种程度上与自动装箱有关,但我真的不知道为什么在使用==运算符和调用.equals时为什么0会被加框

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

   *它是自反的:对于任何非空参考值
   * x,x.equals(x)应该返回
   *是的。

编辑

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

只需将其更改为

 System.out.println(d.equals(0d)); // is false ?! now true 

你正在将double与Integer 0进行比较

在封面下

 System.out.println(d.equals(0)); // is false ?! 

0将自动装箱到IntegerInteger一个实例将被传递给Double类的equals()方法,它将在

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

当然会返回虚假

更新

当您使用==进行比较时,它会比较值,因此不需要autobox,它直接对值进行操作。 where equals()接受Object所以如果你试图调用d1.equals(0)0就不是Object,所以它会执行自动装箱,并将它打包到Integer,这是一个Object。

Number对象类型相同,则数字对象仅等于具有相同值的数字。 那是:

 new Double(0).equals(new Integer(0)); new BigInteger("0").equals(new BigDecimal("0")); 

和类似的组合都是假的。

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

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

 |x - y| < ε, ε very small 

d.equals(0)0是一个intDouble.equals()代码仅对Double对象返回true。

当你表演

 d == 0 

这是向上倾斜的

 d == 0.0 

然而,没有自动装箱的上行规则,即使有等号(对象)没有给出你想要的双击而不是整数的命中。