Сравнение удвоений в 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

Я уверен, что это связано с автобоксированием в некотором роде, но я действительно не знаю , почему 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, который выглядит как Integer, равен true, чем "интуитивно" d.equals(0), также должен быть правдой.

Ответ 1

просто измените его на

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

Вы сравнивали double с Integer 0

Под обложкой

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, конечно.

Обновление

когда вы выполняете сравнение, используя ==, он сравнивает значения, поэтому нет необходимости в autobox, он напрямую действует на значение. Где equals() принимает Object, поэтому, если вы пытаетесь вызвать d1.equals(0), 0 не является Object, поэтому он будет выполнять автобоксинг, и он упакует его в Integer, который является объектом.

Ответ 2

Number объекты равны номерам с одинаковым значением, если они одного типа. То есть:

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

и подобные комбинации - все ложные.

В вашем случае буква 0 помещается в объект Integer.

Ответ 3

Возможно, стоит отметить, что вам следует сравнивать числа с плавающей запятой, например:

|x - y| < ε, ε very small

Ответ 4

d.equals(0): 0 является int. Код Double.equals() возвращает true только для объектов Double.

Ответ 5

Когда вы выполняете

d == 0

это upcast для

d == 0.0

однако нет правил повышения уровня автобоксинга, и даже если они равны (Object) не дает никаких ударов, для которых вы хотите использовать Double вместо Integer.