Skip to main content

🀯 “Why Integer a = 128; Integer b = 128; Broke My Brain”

🎬 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 to cache[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

Popular posts from this blog

🐱 Tomcat vs ⚡ Netty – Which One Should You Use?

🐱 Tomcat vs ⚡ Netty – Which One Should You Use? So recently I got curious about this too πŸ€”. Everywhere in Spring Boot tutorials we see Tomcat . Then suddenly while exploring Spring WebFlux , the name Netty pops up. And I was like – “Wait, who’s this Netty guy trying to replace Tomcat?” πŸ˜… Let’s break it down with real-time examples , icons , and fun comparisons . 🐱 Tomcat – The Traditional Web Server Type: Servlet Container (blocking I/O) World: Used with Spring MVC Style: Thread-per-request model πŸ‘©‍πŸ’» Pros: Stable, widely used, battle-tested Cons: Struggles with huge concurrent connections πŸ‘‰ Example in real life: Tomcat is like a restaurant with fixed waiters 🍴. - Each customer = one thread/waiter - If too many customers come in at once → waiters run out → customers wait outside πŸšͺ ⚡ Netty – The Reactive Rockstar Type: Asynchronous Event-Driven Network Framework World: Default for Spring WebFlux Style: Event-lo...

🎭 Spring’s Secret: Why @Transactional & Friends Betray You Silently

πŸ’‘ Lesson Learned — Not a Prod Bug, But a Real Pain No, this wasn’t a production outage. Nobody screamed at me. But I sat for 3 hours wondering: “Why the heck is my @Transactional not rolling back!?” 😡‍πŸ’« “Why is Redis cache not working?” 🀯 Turned out, the issue was one silent villain: 🧱 Self-invocation 🀷 What Is @Transactional ? If you're new: @Transactional = Tells Spring to start a DB transaction when a method is called. It’ll commit if everything’s okay. It’ll rollback if something fails. 🧠 Think of it like wrapping your code in: try { beginTransaction(); // your logic commit(); } catch(Exception e) { rollback(); } πŸ•΅️ Real-Life Analogy — The Gateway Community 🏘️ Let me tell you about my society — it has a strict watchman at the gate. Here’s how it works: πŸ›‚ Watchman = Spring Proxy 🏠 Your apartment = Your service class πŸšͺ Your room = A method inside that class πŸƒ Scenario 1: Outsider Visits Your friend from outside...

🧡 Virtual Threads in Java — The Ultimate Guide with Diagrams, Code & Interview Qs!

πŸš€ “How are Virtual Threads different from Thread Pools?” 😡 “Are they OS threads or JVM threads?” πŸ™ƒ “Should I still use CompletableFuture?” 🀯 “How do I even use them in real-time microservices?” 🧠 What are Virtual Threads? Virtual Threads (introduced in Java 21 as stable πŸŽ‰) are lightweight threads managed by the JVM instead of the OS kernel. πŸ‘‰ They look like normal threads, but don’t hog OS resources like traditional threads. 🧠 What is the OS Kernel? πŸ›️ OS Kernel = The Brain of the Operating System It’s the core part of your OS (Windows, Linux, Mac) that: Manages memory 🧠 Schedules threads πŸ•’ Talks to hardware πŸ’» Handles I/O operations πŸ“¨ When you create a traditional thread in Java, the JVM asks the OS Kernel to create a real OS-level thread. πŸ–Ό️ Imagine This... ┌───────────────────────────┐ │ Your Java Application │ └────────────┬──────────────┘ │ ...