π¬ Intro — “I Thought I Knew ==… Until Java Proved Me Wrong”
I was casually writing:
Integer a = 128;
Integer b = 128;
System.out.println(a == b); // Output: false ❌
…and confidently told myself:
“Yeah, that’s definitely true.”
π₯ WRONG! Output: false
I was like… π§♂️ “Hello? Java, are you okay?”
Let's break this down, and I’ll show you what I learned — in my usual style: with humor, diagrams, dumb-but-smart questions, and gotchas!
π§ͺ 1. Code Examples That Confused Me
✅ Primitive Comparison Works
int a = 128;
int b = 128;
System.out.println(a == b); // true ✅
➡️ Simple! Both values are 128, both stored in stack. Done.
❌ Object Comparison Fails?
Integer a = 128;
Integer b = 128;
System.out.println(a == b); // false ❌
➡️ Wait, same values, but still false?
✅ Mixed (Object + Primitive)
Integer a = 128;
int b = 128;
System.out.println(a == b); // true ✅
➡️ What? Now it works again?
π§ 2. The Root Cause: Memory Layout (With Diagram!)
Let’s see how these are stored in memory.
π¦ Primitive Example:
int a = 128;
int b = 128;
π Stack Memory:
+--------+ +--------+
| a | 128 | b | 128
+--------+ +--------+
✅ a == b → compares 128 == 128 → ✅ true
π¦ Object Example:
Integer a = 128;
Integer b = 128;
π Stack π§ Heap
+--------+ +-----------------+
| a | ─────┐ | Integer@0xABC |
+--------+ └──────▶ | value = 128 |
+-----------------+
+--------+ +-----------------+
| b | ─────┐ | Integer@0xDEF |
+--------+ └──────▶ | value = 128 |
+-----------------+
❌ a == b → compares 0xABC != 0xDEF → false
π§ 3. So What Does == Actually Do?
Case | What == Compares |
Output |
---|---|---|
int == int |
Primitive values | ✅ true |
Integer == Integer |
Object references (memory) | ❌ false |
Integer == int |
Auto-unboxed to primitive | ✅ true |
π§ Java is smart! It decides based on types at compile time:
- Primitives? → Compare values
- Objects? → Compare reference (i.e., memory address)
- Mix? → Unbox object → Compare values
π§΅ 4. What About Small Numbers?
Integer a = 127;
Integer b = 127;
System.out.println(a == b); // ✅ true
π² Surprise! This one is true. Why?
π₯ 5. Behind-the-Scenes: Integer Caching!
Integer a = 127;
Integer b = 127;
Java caches values from -128 to 127. These are reused from a common pool:
IntegerCache:
-128 → memory@100
...
127 → memory@300
So a == b
→ both point to memory@300 → ✅ true
π§ 6. Gotchas & Surprises
Integer a = 127;
Integer b = 127;
System.out.println(a == b); // ✅ true
Integer x = 128;
Integer y = 128;
System.out.println(x == y); // false ❌
✅ Because 128 is outside the cache range, Java creates new objects.
Want to increase the cache?
-Djava.lang.Integer.IntegerCache.high=256
π§ Where is the Integer Cache (-128 to 127) Stored — Stack or Heap?
✅ Answer:
π In the Heap — specifically as part of the IntegerCache
class inside the Integer
class.
π¦ What exactly happens?
When you write:
Integer a = 100;
Integer b = 100;
System.out.println(a == b); // ✅ true
Java does not create a new object every time for small values (from -128 to 127). Instead, it returns a pre-cached object stored in a static array.
π Internally:
private static class IntegerCache {
static final Integer cache[] = new Integer[-(-128) + 127 + 1];
static {
for (int i = 0; i < cache.length; i++)
cache[i] = new Integer(i - 128);
}
}
- This static
cache[]
is initialized once. - These objects live in the heap memory (because they're part of class static fields).
- So when you do
Integer.valueOf(100)
, Java gives you a reference tocache[100 + 128]
.
πΎ Memory Layout:
Stack (Thread Local)
┌────────────┐
│ Integer a │──┐
└────────────┘ │
┌────────────┐ │
│ Integer b │──┘
└────────────┘
Heap (Shared)
┌────────────────────────┐
│ IntegerCache.cache[] │
│ ┌────┬────┬────┐ │
│ │... │100 │101 │... │ ← π§ shared, reused
│ └────┴────┴────┘ │
└────────────────────────┘
Both a
and b
point to the same Integer
object in the heap when the value is within the cached range.
π₯ What happens outside the range?
Integer x = 128;
Integer y = 128;
System.out.println(x == y); // ❌ false
Integer.valueOf(128)
creates new objects, not from the cache.
π‘ Fun Fact:
You can change the cache range at JVM startup (not recommended):
-Djava.lang.Integer.IntegerCache.high=255
That would cache from -128 to 255.
π§΅ Summary:
Feature | Location |
---|---|
Integer a = 100; |
Stack (reference) |
IntegerCache.cache[] |
Heap (actual cached objects) |
Value outside cache | Heap (new object each time) |
π§ 7. The Dumb Questions That Actually Matter
Question ❓ | Answer ✅ |
---|---|
Is == always reference compare? | ❌ No — depends on types |
Are int and Integer treated same? | ❌ Nope, one is primitive, one is object |
Why is 127 working, 128 not? | Because of Integer cache (−128 to 127) |
Why does Integer == int work? | Java auto-unboxes the object to compare values |
Are object references in stack? | ✅ Yes! But they point to heap objects |
Is there heap involved in int a = 128 ? | ❌ No. Only stack — just raw value |
π 8. Final Rules to Live By (with Emojis π)
- πΉ
int == int
→ ✅ compares values - πΉ
Integer == Integer
→ ❌ compares references - πΉ
Integer == int
→ ✅ unboxes & compares values - πΉ Use
.equals()
to compare objects safely - πΉ Don't rely on
==
unless you're 100% sure of what you're comparing - πΉ Java caches small Integers (−128 to 127) — don’t assume it for all values
π§π» 9. Developer Tip π¬
"If you're not sure whether you're holding a value or a reference, you're probably comparing the wrong thing with ==
."
π Wrapping Up
This one line of code taught me more about Java memory, references, unboxing, and compiler behavior than most tutorials ever did.
The next time you write:
if (a == b)
Ask yourself:
π§ Are you comparing values or just hoping they're pointing to the same object?
π’ Over to You!
- π¨π» Have you ever been shocked by a
==
behaving weirdly? - π± Ever wasted 2 hours debugging a bug that was just a reference comparison?
Comments
Post a Comment