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