Is Java pass-by-value or pass-by-reference? Explain what happens when you pass an object to a method.
answer
- always pass-by-value, no exceptions
- for objects the reference is the copied value
- mutation visible, reassignment not
- swap test proves pass-by-value
- defensive copy / immutability to avoid surprise mutation
basics
~20 sJava is always pass-by-value. For objects, the value copied is the reference, so the method can change the object's fields (the caller sees it), but reassigning the parameter to a new object does not affect the caller's variable.
solid answer
~40 sJava is strictly pass-by-value, with no exceptions. The subtlety is *what* value is copied. For a primitive, the actual value is copied, so the method works on an independent copy. For an object, the *reference* (the handle to the heap object) is copied — not the object. So the parameter and the caller's variable are two separate handles pointing at the same shared object. Because they share the object, mutating it through the parameter (e.g. `list.add(x)` or `dog.setName(...)`) is visible to the caller. But assigning the parameter to a different object (`dog = new Dog()`) only repoints the method's local copy; the caller's variable still points to the original. This is why a method can't swap two object references for the caller, but can mutate the objects they point to.
code
java · 8 linesstatic void mutate(StringBuilder sb) { sb.append("!"); } // affects caller's object
static void reassign(StringBuilder sb) { sb = new StringBuilder("new"); } // does NOT
StringBuilder s = new StringBuilder("hi");
mutate(s);
System.out.println(s); // "hi!" (shared object mutated)
reassign(s);
System.out.println(s); // "hi!" (caller's reference unchanged)go deeper
States Java is pass-by-value and that mutating a passed object affects the caller.
Explains that the reference is the copied value, distinguishing mutation (visible) from reassignment (not), and can demonstrate with code.
Uses the reassignment/swap test as proof, and discusses defensive copying and immutability to control unintended mutation across calls.
Frames it as API contract design: which params are owned vs borrowed, copy-on-entry policies, and how immutability removes a class of aliasing bugs in concurrent code.
## The two competing definitions - **Pass-by-value:** the method receives a *copy* of the argument. Changes to the parameter variable itself don't affect the caller. - **Pass-by-reference:** the method receives an *alias* for the caller's variable; reassigning the parameter would reassign the caller's variable too. **Java is always pass-by-value.** The confusion comes entirely from one fact: for objects, the value being copied is the **reference**, not the object. ## Primitives — copy the value ```java void inc(int n) { n = n + 1; } int x = 5; inc(x); // x is still 5 — n was an independent copy of the value 5 ``` The parameter `n` is a separate variable initialized with a copy of `x`'s value. Nothing the method does to `n` reaches `x`. ## Objects — copy the reference ```java void rename(Dog d) { d.setName("Rex"); } Dog mine = new Dog("Fido"); rename(mine); // mine.getName() is now "Rex" ``` When `rename` is called, the parameter `d` is initialized with a **copy of the reference** held by `mine`. Now `mine` and `d` are two distinct handles that **point at the same Dog on the heap**. `d.setName(...)` reaches through the shared handle and mutates the one object — so the caller sees the change. ## The decisive test — reassignment ```java void replace(Dog d) { d = new Dog("Other"); } // repoints local copy only Dog mine = new Dog("Fido"); replace(mine); // mine still refers to "Fido" — UNCHANGED ``` If Java were pass-by-reference, reassigning `d` would reassign `mine`. It doesn't. Reassigning `d` only changes the method's private copy of the handle; the original object and the caller's variable are untouched. **This is the proof Java is pass-by-value.** ## The classic swap failure ```java void swap(Dog a, Dog b) { Dog t = a; a = b; b = t; } // does nothing useful ``` You cannot write a method that swaps two of the caller's object references, precisely because the method only has copies of the handles. (You *can* swap the contents of a mutable container, because that mutates a shared object.) ## Mental model Think of every argument as photocopied onto the parameter slot. For a primitive, you copy the number. For an object, you copy the *sticky note with the object's address* — both notes point to the same object, but they are different notes. Scribbling a new address on your note (reassignment) doesn't change the caller's note; following your note to the object and editing it (mutation) changes the shared object everyone's notes point to. ## Why this matters in practice - A method receiving a mutable object (a `List`, a `Date`, a domain entity) can mutate it as a side effect — sometimes intended (a builder), sometimes a bug. **Defensive copying** or **immutable types** prevent surprise mutation. - To 'return' multiple values you mutate a passed-in container, return a new object, or use a holder — you cannot reassign the caller's variables.
- Can you write a method that swaps two object references for the caller? Why or why not?No. The method only gets copies of the handles, so reassigning them inside the method doesn't touch the caller's variables. You can only swap the contents of a shared mutable container.
- Why do people wrongly think Java is pass-by-reference?Because mutating a passed object is visible to the caller, which *looks* like reference semantics. But that's just shared state via a copied reference; the giveaway is that reassigning the parameter has no effect on the caller.
You give a friend a photocopy of a note with your house address. They can drive to the house and rearrange your furniture (mutation — you'll see it). But if they scribble a different address on their copy (reassignment), your original note is unchanged — they're just visiting someone else now.
saying these in an interview costs you the question
- Saying Java is pass-by-reference for objects (or 'pass-by-reference for objects, by-value for primitives')
- Claiming a method can swap the caller's two references
- Confusing mutating an object with reassigning the parameter
- Saying the object itself is copied into the method