Ever written a simple Java comparison like Integer a = 128; Integer b = 128;
and got surprised that a == b
returned false
? 🤯 You're not alone.
Let’s unravel this fascinating corner of the Java language where autoboxing, object pooling, and reference comparison collide in unexpected ways.
🧠 The Unexpected Behavior
Integer a = 128;
Integer b = 128;
System.out.println(a == b); // false
Integer x = 1;
Integer y = 1;
System.out.println(x == y); // true
At first glance, both a
and b
are Integer
objects with the same value. So why does a == b
return false
, while x == y
returns true
?
Short Answer:
Java caches Integer objects from -128 to 127. Outside that range, new objects are created — even if the values are the same.
🔍 What's Happening Behind the Scenes?
In Java, Integer
is a wrapper class, and assigning int
to Integer
uses autoboxing. When you do:
Integer x = 1;
Java checks if that number is in the cache. If it is, it reuses the object. This makes:
Integer x = 1;
Integer y = 1;
System.out.println(x == y); // true ✅
Because both point to the same object in memory.
But if the value is outside -128 to 127
:
Integer a = 128;
Integer b = 128;
System.out.println(a == b); // false ❌
New Integer
objects are created each time, so a
and b
point to different memory locations.
🧪 Use .equals()
for Value Comparison
Unlike ==
which checks reference equality, .equals()
compares the actual values:
Integer a = 128;
Integer b = 128;
System.out.println(a.equals(b)); // true ✅
Always use .equals()
when comparing wrapper objects or values from unknown sources.
💡 Customizing the Cache (Advanced)
You can tweak the cache range by setting a JVM option:
-XX:AutoBoxCacheMax=256
This increases the upper bound of cached values. Note: this works only for Integer
, not other wrappers.
🔬 Memory Check Example with System.identityHashCode()
To prove that cached and non-cached Integers are different objects:
Integer c = 128;
Integer d = 128;
System.out.println(System.identityHashCode(c));
System.out.println(System.identityHashCode(d));
Integer e = 1;
Integer f = 1;
System.out.println(System.identityHashCode(e));
System.out.println(System.identityHashCode(f));
You'll observe that:
c
andd
have different hash codes (not cached)e
andf
have same hash code (cached)
🚨 Why This Matters in Real Projects
This behavior can cause hard-to-find bugs when developers rely on ==
for wrapper classes. Some common issues:
- Comparing response values from APIs or databases
- Conditional logic failures in object comparisons
- Test assertions failing unexpectedly
✅ Best Practice: Always Use .equals()
Use .equals()
when comparing:
- Boxed types (
Integer
,Long
, etc.) - Objects from user input or external systems
Use ==
only when:
- Comparing primitives (
int
,long
, etc.) - Checking for exact same object instance (rare)
🎯 Key Takeaways
- Java caches Integer values from
-128
to127
. ==
compares references, not values..equals()
is the correct way to compare object values.- Autoboxing can introduce subtle bugs if not understood well.
Did this save you from a bug? Hit that bookmark or share it with your Java buddies!
Want more Java mysteries decoded? Follow me on GitHub or connect on Instagram. ☕