13

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

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

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

这不是隐含违反equals合同吗?

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

编辑

感谢您的快速回答。我认为它的装箱方式不同,真正的问题是:为什么装箱方式不同?我的意思是,如果d == 0dd.equals(0d)直观和预期的更直观,但是如果d == 0看起来像一个Integer,那么true“直观”d.equals(0)也应该是正确的。

4

5 回答 5

19

只需将其更改为

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

您正在将 double 与Integer0进行比较

在封面下

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

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

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

这当然会返回false

更新

当您使用==它进行比较时,它会比较值,因此不需要自动装箱,它直接对值进行操作。如果您尝试调用Whereequals()接受,则不是 Object,因此它将执行自动装箱并将其打包为 Integer,这是一个 Object。Objectd1.equals(0)0

于 2011-03-08T09:36:50.383 回答
6

Number对象只有在它们属于相同类型时才等于具有相同值的数字。那是:

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

和类似的组合都是假的。

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

于 2011-03-08T09:36:50.397 回答
5

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

|x - y| < ε, ε very small
于 2011-06-29T10:00:56.300 回答
2

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

于 2011-03-08T09:37:47.553 回答
2

当你表演

d == 0

这是向上的

d == 0.0

但是,自动装箱没有向上转换规则,即使有 equals(Object) 也不会给出您想要 Double 而不是 Integer 的命中。

于 2011-03-08T10:07:46.490 回答