Java: Boxed values and equality
When comparing wrapper types such as Integer
s, Long
s or Boolean
s using ==
or !=
, you're comparing them as references, not as values.
If two variables point at different objects, they will not ==
each other, even if the objects represent the same value.
Example: Comparing different Integer
objects using ==
and !=
.
Integer i = new Integer(10);
Integer j = new Integer(10);
System.out.println(i == j); // false
System.out.println(i != j); // true
The solution is to compare the values using equals()
…
Example: Compare objects using .equals(…)
Integer i = new Integer(10);
Integer j = new Integer(10);
System.out.println(i.equals(j)); // true
…or to unbox the operands explicitly.
Example: Force unboxing by casting:
Integer i = new Integer(10);
Integer j = new Integer(10);
System.out.println((int) i == (int) j); // true
Other operators
Arithmetic (+
, *
, …), logical (&&
, ||
, …), bitwise (&
, <<
, …) and commparison operators other than ==
and !=
(<
, <=
, …) are only defined for primitive types, so when applied to boxed types the compiler will automatically unbox the operands.
Example: Operands are unboxed.
Integer i = new Integer(10);
Integer j = new Integer(10);
System.out.println(i <= j); // true
Caching
To complicate matters further, autoboxing reuses cached objects for values between −128 and 127. This causes reference equality to "work" for some boxed values but not for others.
Example: 1 is within caching range, thus i
and j
refer to the same object:
Integer i = 1; // = Integer.valueOf(1)
Integer j = 1; // = Integer.valueOf(1) - result cached
System.out.println(i == j); // true
Example: 300 is not within caching range, thus k
and l
refer to different objects:
Integer k = 300; // = Integer.valueOf(300)
Integer l = 300; // = Integer.valueOf(300) - result not cached
System.out.println(k == l); // false