Java: Boxed values and equality

If you're not already familiar with autoboxing and unboxing, please start here: Java: Autoboxing and unboxing

An operator such as <= is only defined for primitive types, so when applied to, say Integers, the compiler will automatically unbox the operands.

Example: Operands are unboxed.
Integer i = new Integer(1);
Integer j = new Integer(1);
System.out.println(i <= j); // true

This is in fact the case for all operators except == and !=.

Since the == and != operators are defined for reference types, the compiler is not forced to, and will not, unbox the operands.

Example: Operands are not unboxed (and i and j refer to different objects)
Integer i = new Integer(1);
Integer j = new Integer(1);
System.out.println(i == j); // false
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:
  • i and j refer to the same object
  • k and l refer to different objects
Integer i = 1; // = Integer.valueOf(1)
Integer j = 1; // = Integer.valueOf(1) - result cached
System.out.println(i == j); // true

Integer k = 300; // = Integer.valueOf(300)
Integer l = 300; // = Integer.valueOf(300) - result not cached
System.out.println(k == l); // false

Using .equals will however always work as expected!

Example: k and l refer to different objects
Integer k = 300;
Integer l = 300;
System.out.println(k == l);      // false
System.out.println(k.equals(l)); // true

Recommendation: Never rely on == or != for boxed values. Always use .equals or explicit unboxing.

Comments

Be the first to comment!