Trace:

blog:in_java_5_0_is_not_always_equal_to_0

This shows you the differences between two versions of the page.

Both sides previous revision Previous revision | |||

blog:in_java_5_0_is_not_always_equal_to_0 [2008/05/13 11:46] djo Discussion status changed |
blog:in_java_5_0_is_not_always_equal_to_0 [2014/10/17 22:08] (current) |
||
---|---|---|---|

Line 1: | Line 1: | ||

+ | ====== In Java 5, 0 is not always equal to 0 ====== | ||

+ | |||

+ | Much to my surprise yesterday, I discovered that Java 5 believes that 0 != 0 in certain situations. | ||

+ | |||

+ | Try the following in Java 5: | ||

+ | |||

+ | <code java> | ||

+ | System.out.println(0L == 0); | ||

+ | System.out.println(((Long)0L).equals(0)); | ||

+ | </code> | ||

+ | |||

+ | For me, this prints: | ||

+ | |||

+ | <code> | ||

+ | true | ||

+ | false | ||

+ | </code> | ||

+ | |||

+ | A little more investigation yields the following implementation in class Long: | ||

+ | |||

+ | <code java> | ||

+ | public boolean equals(Object obj) { | ||

+ | if (obj instanceof Long) { | ||

+ | return value == ((Long)obj).longValue(); | ||

+ | } | ||

+ | return false; | ||

+ | } | ||

+ | </code> | ||

+ | |||

+ | So, because I'm comparing a boxed Integer with a boxed Long, 0 isn't equal to itself. But if I work with unboxed types, they behave the way I expect. | ||

+ | |||

+ | Mathematically speaking, this behavior of course is absolutely broken. 0 is always 0, no matter what the binary representation. In addition, one could argue that this violates at least the spirit of the API contract for equals: | ||

+ | |||

+ | <code java> | ||

+ | /** | ||

+ | * It is reflexive: for any non-null reference value | ||

+ | * x, x.equals(x) should return | ||

+ | * true. | ||

+ | * .... | ||

+ | */ | ||

+ | </code> | ||

+ | |||

+ | I understand that technically Integer(0) and Long(0) aren't the same thing. However, as an object oriented abstraction, they are certainly intended to represent exactly the same value. | ||

+ | |||

+ | Mathematically speaking, Integer(0) and Long(0) both represent the number zero with exactly the same amount of precision. Mathematical precision for the Integer 0 is the same regardless of the number of binary 0s there are, so in no sense is there ever any round-off error for binary zero, no matter the representation. | ||

+ | |||

+ | Consequently, it would seem to make much more sense for Integer(0) and Long(0L), and by analogy, Float(0.0f) and Double(0.0) to be treated by the language as exactly the same number. Similarly, it seems that the pairs (Integer(0) and 0) and (Long(0L) and 0L) should have interchangeable semantics--especially in a language where autoboxing can automagically convert 0 to Integer(0) and Long(0) to 0L and back. | ||

+ | |||

+ | At a minimum, this behavior certainly violates the principle of least surprise. Maybe there's a good reason for this, but I can't think of one right now. | ||

+ | |||

+ | If there is a good reason, perhaps someone could help me to understand it? | ||

+ | |||

+ | ~~LINKBACK~~ | ||

+ | ~~DISCUSSION:closed~~ | ||

Except where otherwise noted, content on this wiki is licensed under the following license: CC Attribution 4.0 International