有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

在Java中比较double会得到奇怪的结果

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

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

我肯定这在某种程度上与自动装箱有关,但我真的不知道当使用==运算符和调用.equals0的装箱方式会有所不同

这难道不意味着违反了equals合同吗

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

编辑

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


共 (5) 个答案

  1. # 1 楼答案

    把它改成

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

    您正在将double与Integer0进行比较

    在封面下

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

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

    @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不是对象,因此它将执行自动装箱,并将其打包为作为对象的整数

  2. # 2 楼答案

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

  3. # 3 楼答案

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

    |x - y| < ε, ε very small
    
  4. # 4 楼答案

    Number对象只有在其类型相同时才等于具有相同值的数字。即:

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

    类似的组合都是错误的

    在您的例子中,文本0被装箱到Integer对象中

  5. # 5 楼答案

    当你表演的时候

    d == 0
    

    这是向上的

    d == 0.0
    

    但是,自动装箱没有向上转换的规则,即使有equals(Object),也不会给出想要双精度而不是整数的命中率