Naturally, as expected, somebody came up with this example in Java:
Integer foo = 1000;
Integer bar = 1000;
foo == bar; // false
and calls it "Fun with auto boxing and the integer cache in Java."
Browsing the web, it seems that this "feat" has been blogged about in other occasions as well (e.g. Autoboxing pitfalls when comparing numbers with “==”, ).
Despite the fact that it may be "odd" for some observers, there are two facts that disturb me about the way its presented:
1) it is perfectly specified behavior that will most likely not change; and
2) there is no autoboxing involved at all.
Here is what really happens:
foo==bar;
is an equality operator expression, as specified in the Java Language Specification, 15.21 Equality Operators.
The specification in 15.21.1 Numerical Equality Operators == and != clearly states:
If the operands of an equality operator are both of numeric type,
or one is of numeric type and the other is convertible (§5.1.8) to numeric type,
binary numeric promotion is performed on the operands (§5.6.2).
If the promoted type of the operands is int or long, then an integer equality test is performed;
if the promoted type is float or double, then a floating-point equality test is performed.
Note that binary numeric promotion performs value set conversion (§5.1.13) and unboxing
conversion (§5.1.8). Comparison is carried out accurately on floating-point values,
no matter what value sets their representing values were drawn from.
Now, the key part here is are both of numeric type, or one is of numeric type and the other is convertible.
Integer is NOT a numeric type (see 4.1 The Kinds of Types and Values), but rather a reference type, and the section 15.21.3 Reference Equality Operators == and != applies.
Summing up, if it is a pitfall at all, then it is the fact that the equality operand applies equivalence according to the types of the operands. However, specially in Java this has been known since quite a long while: remember String equality?
Maybe it is rather an expected result.
Objects in Java should always be compared with the equals method and primitive type wrappers ARE Objects.
As a side note on the surprise about implementations caching primitive type objects, well, all of these primitive wrappers and Strings are immutable (i.e. objects whose state cannot change after construction), so there can't be any "real" surprise if one and the same instance is shared.
Just always remember, for reference types, reference equality applies, so for cached instances, the reference equality operation may return true:
Integer foo = 42;
Integer bar = 42;
foo == bar; // may be true




