Is Java pass-by-value or pass-by-reference? Explain what actually gets passed when you call a method.
answer
- Always pass-by-value, no exceptions
- Object value = the reference, copied
- Mutate shared object: yes; reseat caller's var: no
- Photocopy of the address paper
- Reassignment inside method = litmus test
basics
~10 sJava is always pass-by-value. The method gets a copy of the argument. For an object, that copy is a copy of the reference (the address), not a copy of the object itself.
solid answer
~50 sJava is strictly pass-by-value, with no exceptions. When you call a method, each argument's value is copied into the method's parameter. For a primitive like int, the actual number is copied, so changing the parameter inside the method has no effect on the caller's variable. For an object, the value being copied is the reference (a pointer to the heap object), not the object. So the parameter and the caller's variable point at the same object: the method can mutate that shared object and the caller will see the changes, but the method cannot make the caller's variable point at a different object. People say Java is pass-by-reference for objects, but that is wrong; it passes the reference by value. The distinction matters because reassigning a parameter never affects the caller, while mutating the referenced object does.
code
java · 13 linesclass Dog { String name; Dog(String n){ name = n; } }
static void mutate(Dog p) { p.name = "Rex"; } // changes shared object
static void reseat(Dog p) { p = new Dog("Rex"); } // local-only, no effect
static void inc(int p) { p = p + 1; } // local-only, no effect
public static void main(String[] a) {
Dog d = new Dog("Fido");
mutate(d); System.out.println(d.name); // Rex (object mutated)
reseat(d); System.out.println(d.name); // Rex (still old object)
int x = 5;
inc(x); System.out.println(x); // 5 (primitive unchanged)
}go deeper
State the rule confidently: Java is always pass-by-value; for objects the copied value is the reference. Distinguish mutating an object (visible to caller) from reassigning the parameter (not visible).
Walk through all three cases (primitive, mutate, reassign) and explain WHY using the 'copied pointer to the same heap object' model. Correctly debunk the 'pass-by-reference for objects' myth.
Articulate the precise terminology (value = the reference), connect to immutability/defensive copying, and explain practical consequences for API design (you can't output through a param; mutation is a side effect to document).
Frame it against other languages (C++ references, C# ref/out, true reference semantics), discuss the design rationale, and how it shapes guidance on immutability, defensive copies, and avoiding hidden mutation in shared codebases.
## The terms first **Argument vs parameter.** When you write `foo(x)`, `x` is the *argument*. Inside `void foo(int p)`, `p` is the *parameter*. Argument binding is the step where the argument's value flows into the parameter. **Pass-by-value** means: the parameter receives a *copy* of the argument's value. Changes to the parameter do not flow back to the argument. **Pass-by-reference** means: the parameter becomes an *alias* for the caller's variable itself — assigning to the parameter reassigns the caller's variable. Java does **not** do this. (C++ does, with `int&`; C# does with `ref`.) ## What is a 'value' in Java? Java has exactly two kinds of types: 1. **Primitives** (`int`, `long`, `double`, `boolean`, `char`, etc.). A primitive variable *holds the actual data* — the number 5, the boolean true. 2. **Reference types** (every object, array, and `String`). A reference variable does **not** hold the object. It holds a *reference* — think of it as the address/handle of an object that lives on the heap. The object itself is a separate thing. So when we ask 'what is the value of variable `v`?': - If `v` is `int v = 5`, its value is `5`. - If `v` is `Dog v = new Dog()`, its value is *the reference* — the handle pointing at the Dog on the heap. It is **not** the Dog. ## The single rule Java copies the **value** of the argument into the parameter. Always. That is the whole story. The confusion comes only from forgetting that for objects, the value *is the reference*. ### Case A: primitive argument ```java void inc(int p) { p = p + 1; } int x = 5; inc(x); // x is still 5 ``` The value `5` is copied into `p`. `p` and `x` are independent boxes. Incrementing `p` cannot touch `x`. ### Case B: object argument — mutation ```java void rename(Dog p) { p.setName("Rex"); } Dog d = new Dog("Fido"); rename(d); // d.getName() is now "Rex" ``` The *reference* in `d` is copied into `p`. Now `d` and `p` are two separate variables that hold the *same* reference — they point at the *same* Dog on the heap. Following either pointer reaches the one Dog, so `p.setName` mutates the object the caller can see. This is real and surprises people, but it is still pass-by-value: a copy of the pointer was passed. ### Case C: object argument — reassignment ```java void replace(Dog p) { p = new Dog("Rex"); } Dog d = new Dog("Fido"); replace(d); // d still refers to "Fido" ``` Here `p` is made to point at a brand-new Dog. But `p` is just a *copy* of the reference. Reseating `p` does nothing to `d`. The caller's variable still points at the original Dog. This is the litmus test that proves Java is not pass-by-reference: if it were, `d` would now be "Rex". ## The mental model Imagine a reference is a piece of paper with a house address written on it. Passing an object to a method = **photocopying** the paper and handing over the copy. The method can drive to the house and repaint it (mutation — you'll see the new color). But if the method scribbles a different address on *its* photocopy, *your* original paper is untouched (reassignment — no effect). ## Why it matters - A method **can** change the contents/state of an object you pass it (unless it's immutable). Don't assume passing an object protects it. - A method **cannot** make your variable point somewhere else. 'Output parameters' don't exist in Java; to return a new object you must `return` it. - This is why people use wrapper objects, arrays of length 1, or holder classes when they want a method to 'hand back' a value through a parameter — they mutate the shared container rather than reassign the variable.
- If Java passes the reference by value, why can a method still change the object I passed in?Because the copied reference points at the SAME heap object as the caller's reference. Both pointers reach one object, so mutating through either is visible to both. What the method cannot do is make the caller's variable point at a different object.
- How can you make a method 'return' a value through a parameter, given Java can't reseat the caller's variable?Pass a mutable container the method writes into: a single-element array, a holder/wrapper object, a StringBuilder, or an AtomicReference. The method mutates the shared object's contents rather than reassigning the parameter.
saying these in an interview costs you the question
- Saying Java is pass-by-reference for objects (it passes the reference BY VALUE)
- Claiming primitives are by value but objects are by reference
- Believing a method can change which object the caller's variable points to
- Confusing mutating the object's state with reassigning the parameter