87. The Integer Cache Trap
Integer.valueOf(n) caches instances for n in [-128, 127] โ so == returns true in that range but false outside it; always use .equals() to compare Integer objects.
Explanation
Integer.valueOf(int) is specified to cache Integer instances for values in the range -128 to 127 (inclusive). This means multiple calls with the same value in that range return the same object. Autoboxing uses Integer.valueOf(), so autoboxed integers in that range also share instances.
The trap: Integer a = 127; Integer b = 127; a == b is true (same cached object). Integer a = 128; Integer b = 128; a == b is false (different objects, cache exhausted). This inconsistency is a notorious interview question and a real bug source.
The fix: always use .equals() to compare Integer, Long, Double, and other wrapper objects. Never use == for reference type comparison unless you explicitly want identity equality. The JVM can extend the cache range with -XX:AutoBoxCacheMax=<N>, making the boundary non-portable.
Example
public class IntegerCacheTrap {
public static void main(String[] args) {
// In cache range (-128 to 127): == returns true
Integer a = 100;
Integer b = 100;
System.out.println("100 == 100: " + (a == b)); // true (cached)
System.out.println("100 eq 100: " + a.equals(b)); // true
// Outside cache range: == returns false
Integer c = 200;
Integer d = 200;
System.out.println("200 == 200: " + (c == d)); // false! (not cached)
System.out.println("200 eq 200: " + c.equals(d)); // true (always correct)
// Boundary: 127 is last cached, 128 is first uncached
Integer e = 127; Integer f = 127;
Integer g = 128; Integer h = 128;
System.out.println("127 same obj: " + (e == f)); // true
System.out.println("128 same obj: " + (g == h)); // false
// Explicit valueOf: same caching behaviour as autoboxing
Integer i = Integer.valueOf(127);
Integer j = Integer.valueOf(127);
System.out.println("valueOf(127): " + (i == j)); // true
// Other wrapper caches:
// Boolean: TRUE and FALSE are always the same instances
Boolean bt = Boolean.valueOf(true);
Boolean bf = Boolean.valueOf(true);
System.out.println("Boolean == : " + (bt == bf)); // true
// Character: caches 0-127
Character ca = 'A'; // 65, in cache
Character cb = 'A';
System.out.println("'A' == 'A': " + (ca == cb)); // true
// Rule: ALWAYS use .equals() for wrapper types!
System.out.println("\nSafe comparison: always .equals()");
System.out.println(c.equals(d)); // true โ reliable
}
}Sources
- https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/lang/Integer.html#valueOf(int) โ Integer.valueOf caching spec
- https://docs.oracle.com/javase/specs/jls/se21/html/jls-5.html#jls-5.1.7 โ JLS: boxing conversions