PrepZone Logo
PrepZone

Java Is Always Pass-by-Value

The single rule that explains why a method can mutate your object but never reassign your variable.

Read these first

Why this matters

  • This one rule explains why a method sometimes appears to modify your data and sometimes appears to ignore your changes entirely.
  • "Does Java pass by reference?" is asked constantly, and the confident wrong answer is the most common one.
  • Once you hold this rule, defensive copying and immutability stop feeling like ceremony and start looking necessary.

The rule, applied twice

Java is always pass-by-value. There is no second mode. What differs is what the value is.

  • For a primitive, the value is the number itself. The method gets its own copy, and changes to it are invisible outside.
  • For an object, the value is the reference — the address of the object. The method gets its own copy of that address.
  • Two copies of the same address point at one object, so mutating through either is visible to both.
  • Reassigning the parameter only overwrites the method's private copy of the address. The caller's variable is untouched.
Caller
cartholds reference #A1
Method parameter
inputcopy of reference #A1
Cart object #A1items = [book]

input.add(pen) is visible to the caller. input = new Cart() is not — it only repoints the copy.

Java copies the value in the variable. For an object that value is the reference, so the method can change the object's fields but cannot repoint the caller's variable.

Primitives: completely isolated

Java
static void increment(int value) {
    value = value + 1;
    System.out.println("inside:  " + value);
}

public static void main(String[] args) {
    int count = 10;
    increment(count);
    System.out.println("outside: " + count);
}
Java
inside:  11
outside: 10

The method received a copy of 10. Nothing it does to that copy can reach count.

Objects: mutation travels, reassignment does not

This is the pair of behaviours that confuses people, and seeing them side by side settles it.

Java
static void mutate(StringBuilder text) {
    text.append(" world");           // changes the shared object
}

static void reassign(StringBuilder text) {
    text = new StringBuilder("replaced");   // changes only the local copy
    text.append("!");
}

public static void main(String[] args) {
    StringBuilder greeting = new StringBuilder("hello");

    mutate(greeting);
    System.out.println(greeting);     // hello world

    reassign(greeting);
    System.out.println(greeting);     // hello world — unchanged
}
Java
hello world
hello world

Both methods received the same address. The first used it to reach the object and modify it. The second threw it away and pointed its own copy somewhere else, which the caller never learns about.

Why swap cannot work

The classic demonstration. There is no way to write a general swap in Java.

Java
static void swap(Integer a, Integer b) {
    Integer temp = a;
    a = b;
    b = temp;
}

public static void main(String[] args) {
    Integer first = 1, second = 2;
    swap(first, second);
    System.out.println(first + ", " + second);   // 1, 2 — nothing happened
}

The method swapped its own two local copies and then returned. Caller variables cannot be rebound from inside a method, full stop. If you need to exchange values, return them — in a record, an array, or by assigning at the call site.

Strings look like an exception but are not

Java
static void change(String text) {
    text = text.toUpperCase();     // creates a new String, rebinds the local copy
}

public static void main(String[] args) {
    String name = "java";
    change(name);
    System.out.println(name);       // java
}

String is immutable, so every operation returns a new object rather than modifying the existing one. There is no mutation available to be visible, and the reassignment is local. Both halves of the rule point the same way.

What this means for your API design

AspectParameter typeWhat a caller should expect
int, double, booleanCompletely safeThe method cannot affect the caller's value
String, Integer, LocalDateSafe — immutableNo mutation is possible
List, Map, arraysMutable and sharedThe method may add, remove or clear
Your own mutable classMutable and sharedAnything with a setter can be changed
  • int, double, boolean

    Parameter typeCompletely safe
    What a caller should expectThe method cannot affect the caller's value
  • String, Integer, LocalDate

    Parameter typeSafe — immutable
    What a caller should expectNo mutation is possible
  • List, Map, arrays

    Parameter typeMutable and shared
    What a caller should expectThe method may add, remove or clear
  • Your own mutable class

    Parameter typeMutable and shared
    What a caller should expectAnything with a setter can be changed

Immutability is what makes a parameter genuinely safe to hand over.

Common misreadings

  • "Objects are passed by reference." The reference is passed by value. The distinction is the entire point, and the phrase "pass by reference value" captures it better.
  • "Mutation proves pass-by-reference." True pass-by-reference would let a method rebind the caller's variable. Java never allows that.
  • "final on a parameter changes the semantics." It only stops reassignment inside the method, which was already invisible outside.
  • "Strings behave differently." They behave identically. Immutability simply removes one of the two options.

Quick recall

Everything you need if you only revisit this box.

  • Java is always pass-by-value. For objects, the value copied is the reference.
  • A method can mutate the object you handed it, because both references point at the same object.
  • A method cannot rebind your variable. Reassigning a parameter affects only the method's copy.
  • Therefore swap is impossible; return the new values instead.
  • Primitives and immutable objects are safe to pass; mutable collections and your own setter-bearing classes are not.
  • Copy defensively when a method must not modify a collection it receives.

Test yourself

Answer these before moving on — recall is what makes it stick.