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

时间:2011-03-08 09:34:08

标签: java double equals autoboxing

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

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在使用==运算符和{ {1}}被称为

这是否隐含违反了.equals合同?

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

修改

感谢快速解答。我认为它的盒装方式不同,真正的问题是:为什么盒装方式不同?我的意思是,如果equalsd == 0d更直观且预期,这会更直观,但如果d.equals(0d) d == 0 Integer比“{1}}更直观” 'true也应该是真的。

5 个答案:

答案 0 :(得分:18)

将其更改为

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

您将双倍与Integer 0

进行比较

在封面下

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

0将自动退回到Integer,并且整数的实例将传递到equals()类的Double方法,在那里它会比较

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

当然会返回 false

更新

当您使用==进行比较时,它会比较值,因此不需要自动装箱,它会直接对值进行操作。 equals()接受Object的位置,因此如果您尝试调用d1.equals(0)0不是对象,那么它将执行自动装箱,并将其打包到Integer,这是一个Object。 / p>

答案 1 :(得分:6)

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

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

和类似的组合都是假的。

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

答案 2 :(得分:5)

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

|x - y| < ε, ε very small

答案 3 :(得分:2)

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

答案 4 :(得分:2)

执行时

d == 0

这是向上转发

d == 0.0

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