Java Language Common Java Pitfalls Pitfall: using == to compare primitive wrappers objects such as Integer


(This pitfall applies equally to all primitive wrapper types, but we will illustrate it for Integer and int.)

When working with Integer objects, it is tempting to use == to compare values, because that is what you would do with int values. And in some cases this will seem to work:

Integer int1_1 = Integer.valueOf("1");
Integer int1_2 = Integer.valueOf(1);

System.out.println("int1_1 == int1_2: " + (int1_1 == int1_2));          // true
System.out.println("int1_1 equals int1_2: " + int1_1.equals(int1_2));   // true

Here we created two Integer objects with the value 1 and compare them (In this case we created one from a String and one from an int literal. There are other alternatives). Also, we observe that the two comparison methods (== and equals) both yield true.

This behavior changes when we choose different values:

Integer int2_1 = Integer.valueOf("1000");
Integer int2_2 = Integer.valueOf(1000);

System.out.println("int2_1 == int2_2: " + (int2_1 == int2_2));          // false
System.out.println("int2_1 equals int2_2: " + int2_1.equals(int2_2));   // true

In this case, only the equals comparison yields the correct result.

The reason for this difference in behavior is, that the JVM maintains a cache of Integer objects for the range -128 to 127. (The upper value can be overridden with the system property "java.lang.Integer.IntegerCache.high" or the JVM argument "-XX:AutoBoxCacheMax=size"). For values in this range, the Integer.valueOf() will return the cached value rather than creating a new one.

Thus, in the first example the Integer.valueOf(1) and Integer.valueOf("1") calls returned the same cached Integer instance. By contrast, in the second example the Integer.valueOf(1000) and Integer.valueOf("1000") both created and returned new Integer objects.

The == operator for reference types tests for reference equality (i.e. the same object). Therefore, in the first example int1_1 == int1_2 is true because the references are the same. In the second example int2_1 == int2_2 is false because the references are different.