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:
canddhave different hash codes (not cached)eandfhave 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
-128to127. ==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. ☕
