Java: Boxed values and equality

When comparing wrapper types such as Integers, Longs or Booleans 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

Comments

Be the first to comment!