Memra

Pass-by-value: the most-misunderstood Java rule

◈ 4 cards

Java is always pass-by-value — even for objects. What that means precisely.

Java is always pass-by-value

When you call a method, the value of each argument is copied into the parameter. For primitives, that's the numeric value. For objects, that's the reference (memory address) — not the object itself.

Primitive — the caller's variable is unaffected:

static void doubleIt(int n) { n = n * 2; }

int x = 5;
doubleIt(x);
System.out.println(x); // 5 — unchanged; doubleIt got a copy

Reference — the object is shared, but reassigning the parameter doesn't affect the caller:

static void clear(StringBuilder sb) {
    sb.setLength(0);  // mutates the shared object — CALLER SEES THIS
}

static void replace(StringBuilder sb) {
    sb = new StringBuilder("new"); // reassigns the local copy — CALLER DOES NOT see this
}

StringBuilder buf = new StringBuilder("hello");
clear(buf);
System.out.println(buf);   // "" — mutation is visible

buf = new StringBuilder("hello");
replace(buf);
System.out.println(buf);   // "hello" — reassignment not visible

The key insight: mutating the object through the reference propagates (caller and method share the same object), but reassigning the parameter variable only changes the local copy — the caller's reference is untouched.

same addressbufcallersbparameter"hello"one StringBuildersetLength(0) — the caller sees it
Passing an object copies the arrow, not the box. sb.setLength(0) empties the one object both names reach, so the caller prints an empty string afterwards.
reassignedbufcallersbparameter"hello"still the caller’s"new"unreachablethe caller never sees "new"
Reassigning the parameter moves only the method’s own arrow. Nothing writes to buf, so the caller still prints "hello" after replace returns.
NORMAL ~/memra/learn/java-from-zero/pass-by-value utf-8 LF