I really can'get my head around why the following happens:
Double d = 0.0;
System.out.println(d == 0); // is true
System.out.println(d.equals(0)); // is false ?!
This however works as expected:
Double d = 0.0;
System.out.println(d == 0.0); // true
System.out.println(d.equals(0.0)); // true
I'm positive that this is related to autoboxing in some way, but I really don't know why 0
would be boxed differently when the ==
operator is used and when .equals
is called.
Doesn't this implicitly violate the equals
contract ?
* It is reflexive: for any non-null reference value * x, x.equals(x) should return * true.
EDIT:
Thanks for the fast answers. I figured that it is boxed differently, the real question is: why is it boxed differently ? I mean that this would be more intuitive if d == 0d
than d.equals(0d)
is intuitive and expected, however if d == 0
which looks like an Integer
is true
than 'intuitively' d.equals(0)
should also be true.
just change it to
System.out.println(d.equals(0d)); // is false ?! now true
You were comparing double with Integer
0
System.out.println(d.equals(0)); // is false ?!
0
will be autoboxed to Integer
and an instance of Integer will be passed to equals()
method of Double
class, where it will compare like
@Override
public boolean equals(Object object) {
return (object == this)
|| (object instanceof Double)
&& (doubleToLongBits(this.value) == doubleToLongBits(((Double) object).value));
}
which is going to return false of course.
when you do comparison using ==
it compares values so there is no need to autobox , it directly operates on value. Where equals()
accepts Object
so if you try to invoke d1.equals(0)
, 0
is not Object so it will perform autoboxing and it will pack it to Integer which is an Object.