Skip to main content

๐Ÿšš Pass By Value vs Pass By Reference in Java — The Great Confusion Buster ๐Ÿ’ฃ

 

๐Ÿ’ฌ “I changed the object inside a method. But when I came back… NOTHING happened.
Java, are you even listening to me?!” ๐Ÿ˜ก

That was me. Screaming at my screen.

So I decided to dig deep: What’s really going on?

Let’s go from basics → to bugs → to JVM internals → to truth ๐Ÿ’ก


๐ŸŽฏ What People Think Java Does:


public void change(int x) { x = 10; }

“Cool, this is pass-by-value. Just a copy. I get it.” ✅

But then...


public void update(User u) { u.setName("Anand"); }

“Wait, it changed outside! That must be pass-by-reference!” ❓

And then...


public void update(User u) { u = new User("NewGuy"); }

“Now it DIDN’T change outside?!  Java, are you drunk?” ๐Ÿบ


๐Ÿง  Truth Bomb: Java is Always Pass-by-Value. No Exceptions.

Even for objects.

But here's the tricky twist:

๐Ÿ“Œ Java passes a copy of the reference when dealing with objects.

So you're not passing the object directly —
You're passing a copy of the pointer to the object.


๐Ÿ” Code Time!

๐Ÿ”น Example 1: Primitives — True Pass-by-Value


public void change(int x) { x = 10; } int a = 5; change(a); System.out.println(a); // prints 5 ❌ no change

๐Ÿ“ฆ Memory (Stack Only — Primitives)

Stack: ----------- | a = 5 | // main method variable ----------- | x = 5 | // method receives a copy ----------- Inside method: x = 10; // Only updates local copy. No effect on 'a'

๐Ÿง  What happened? Java passed the value 5 to x, changed x to 10, but a is untouched.


๐Ÿ”น Example 2: Object Reference – Mutating Object


public void update(User u) { u.setName("Anand"); } User user = new User("Old"); update(user); System.out.println(user.name); // prints "Anand" ✅ changed

๐Ÿ“ฆ Memory (Stack + Heap)


Stack: Heap: ---------- ------------------- | user | ----ref----> | User object | ---------- | name = "Old" | ------------------- Inside method: ---------- ------------------- | u | ----ref----> | same User object | ---------- ------------------- After u.setName("Anand"): Heap: ------------------- | name = "Anand" | ✅ updated! -------------------

๐Ÿง  What happened? Java passed a copy of the reference. You didn’t change the reference — you modified the object it points to. So changes are visible outside.


๐Ÿ”น Example 3: Object Reference – Reassigning Object


public void update(User u) { u = new User("NewGuy"); } User user = new User("Old"); update(user); System.out.println(user.name); // prints "Old" ❌ no change

๐Ÿ“ฆ Memory (Stack + Heap)


Before reassignment: Stack: Heap: ---------- ------------------- | user | ----ref----> | User object | ---------- | name = "Old" | ------------------- Inside method: ---------- ------------------- | u | ----ref----> | same User object | ---------- ------------------- Now we do: u = new User("NewGuy"); After reassignment: Stack: ---------- ------------------- ------------------- | u | --ref--> | User("NewGuy") | ✅ new object ---------- ------------------- ------------------- BUT... user in main() still points to: ------------------- | name = "Old" | ❌ unchanged -------------------

๐Ÿง  What happened? You created a new object inside the method and made u point to it — but user in the calling method is still pointing to the old one.

 


๐Ÿค” Why Java Did This? Internals and Design Reasons

Java designers chose pass-by-value for simplicity and predictability.

  • No dangling pointers

  • No accidental object sharing

  • Easy GC (Garbage Collection)

  • No real pointer arithmetic mess like in C++

๐Ÿ” Java hides pointers from us — but under the hood, everything is still pointer logic.


๐Ÿคช Silly Questions We’ve All Asked

❓Can Java ever do pass-by-reference?
Nope. Not even on Sundays. ๐Ÿ™…‍♂️

❓Then how can I simulate it?
Wrap it in another object (e.g., Holder<T> or an array):


void swap(int[] arr) { int temp = arr[0]; arr[0] = arr[1]; arr[1] = temp; }

❓So when I change object fields — it works. But when I reassign, it doesn’t?


Yes. Welcome to Pass-by-Reference Confusion Club™


๐Ÿ”ฅ Real Bug from a Production App


public void reset(Config c) { c = new Config(); // thought this reset everything }

The dev thought this resets the config across the app.
But it only changed the local reference.
The global config stayed stale. ๐Ÿคฆ‍♂️

Fix:

public void reset(Config c) { c.clear(); // actually mutate the object }

๐ŸŽจ Wrapping Up 

ConceptJava Does?What Happens
Pass-by-Value (primitive)A copy of the value is passed
Pass-by-Value (object reference)A copy of the reference (pointer) is passed
Pass-by-Reference (like in C++)Not possible

๐Ÿ” So next time someone says:

“Java passes objects by reference!”

You say:

“Nah bro. Java passes references by value — big difference!” ๐Ÿ˜


๐Ÿ’ก Final Tip for Interviews:

Interviewer:

“Is Java pass-by-reference or pass-by-value?”

You:

“Always pass-by-value. Even for objects — Java passes a copy of the reference. That’s why mutations work, but reassignments don’t.”

Mic drop. ๐ŸŽค

Stay curious, stay nerdy,
– Anand ๐Ÿš€

Comments

Popular posts from this blog

๐Ÿ” Is final Really Final in Java? The Truth May Surprise You ๐Ÿ˜ฒ

๐Ÿ’ฌ “When I was exploring what to do and what not to do in Java, one small keyword caught my eye — final . I thought it meant: locked, sealed, frozen — like my fridge when I forget to defrost it.”   But guess what? Java has its own meaning of final… and it’s not always what you expect! ๐Ÿ˜… Let’s break it down together — with code, questions, confusion, jokes, and everything in between. ๐ŸŽฏ The Confusing Case: You Said It's Final... Then It Changed?! ๐Ÿซ  final List<String> names = new ArrayList <>(); names.add( "Anand" ); names.add( "Rahul" ); System.out.println(names); // [Anand, Rahul] ๐Ÿคฏ Hold on... that’s final , right?! So how on earth is it still changing ? Time to dive deeper... ๐Ÿง  Why Is It Designed Like This? Here’s the key secret: In Java, final applies to the reference , not the object it points to . Let’s decode this like a spy mission ๐Ÿ•ต️‍♂️: Imagine This: final List<String> names = new ArrayList <>(); Be...

๐ŸŒŸ My Journey – From Zero to Senior Java Tech Lead ๐ŸŒŸ

 There’s one thing I truly believe… If I can become a Java developer, then anyone in the world can. ๐Ÿ’ฏ Sounds crazy? Let me take you back. ๐Ÿ•“ Back in 2015… I had zero coding knowledge . Not just that — I had no interest in coding either. But life has its own plans. In 2016, I got a chance to move to Bangalore and joined a Java course at a training center. That’s where it all started — Every day, every session made me feel like: "Ohhh! Even I can be a developer!" That course didn’t just teach Java — it gave me confidence . ๐Ÿงช Two Life-Changing Incidents 1️⃣ The Interview That Wasn't Planned Halfway through my course, I had to urgently travel to Chennai to donate blood to a family member. After that emotional rollercoaster, I found myself reflecting on my skills and the future. The next day, as I was preparing for my move to Bangalore to complete the remaining four months of my course, I randomly thought — "Let me test my skills... let me just see...

๐ŸŽข Java Loops: Fun, Fear, and ForEach() Fails

๐ŸŒ€ Oops, I Looped It Again! — The Ultimate Java Loop Guide You Won't Forget “I remember this question from one of my early interviews — I was just 2 years into Java and the interviewer asked, ‘Which loop do you prefer and why?’” At first, I thought, “Duh! for-each is cleaner.” But then he grilled me with cases where it fails. ๐Ÿ˜ต That led me to explore all loop types, their powers, and their pitfalls. Let’s deep-dive into every major Java loop with examples &  real-world guidance so you'll never forget again. ๐Ÿ” Loop Type #1: Classic For Loop — “The Old Reliable” ✅ When to Use: You need an index You want to iterate in reverse You want full control over loop mechanics ✅ Good Example: List<String> names = List.of("A", "B", "C"); for (int i = 0; i < names.size(); i++) { System.out.println(i + ": " + names.get(i)); } ๐Ÿ”ฅ Reverse + Removal Example: List<String> item...