Reputation: 7792
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.
Upvotes: 14
Views: 21820
Reputation: 9424
It's probably worth noting that you should compare floating point numbers like this:
|x - y| < ε, ε very small
Upvotes: 5
Reputation: 240870
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.
Upvotes: 20
Reputation: 533492
When you perform
d == 0
this is upcast to
d == 0.0
however there are no upcasting rules for autoboxing and even if there were equals(Object) gives no hits that you want a Double instead of an Integer.
Upvotes: 2
Reputation: 24791
d.equals(0)
: 0
is an int
. The Double.equals()
code will return true only for Double
objects.
Upvotes: 2
Reputation: 76057
Number
objects only equal to numbers with the same value if they are of the same type. That is:
new Double(0).equals(new Integer(0));
new BigInteger("0").equals(new BigDecimal("0"));
and similar combinations are all false.
In your case, the literal 0
is boxed into an Integer
object.
Upvotes: 6