Skip to content

25 · 32 · 5 min

What a variable actually holds

A variable holding an object does not hold the object. It holds a reference to it, and almost every surprising assignment result follows from that.

Stack and heap

java
void process() {
    int count = 5;                  // the value, on the stack
    Order o = new Order();          // object on the heap, reference on the stack
}

The stack frame disappears when the method returns. The heap object survives as long as something references it.

Assignment copies the reference

java
Order a = new Order("x");
Order b = a;
b.setId("y");
a.getId();      // "y": one object, two references

Passing to a method

Java is always pass by value. The subtlety is that the value being passed is the reference.

java
void rename(Order o) { o.setId("changed"); }     // caller sees it
void replace(Order o) { o = new Order("new"); }  // caller sees nothing

The first modifies the object both references point at. The second points the local parameter somewhere else, which the caller's variable knows nothing about.

This one distinction explains most confusion about "does Java pass by reference". It does not; it passes references by value.

LanguagePasses
Javaalways by value; object variables are references
Pythonreferences by value, same behaviour
C++by value by default, by reference with &
Cby value; pass a pointer for the same effect

The mutable default argument

python
def add(item, items=[]):     # the list is created once, at definition
    items.append(item)
    return items

add("a")     # ['a']
add("b")     # ['a', 'b']   not a fresh list

The default is one object shared by every call that omits the argument. The fix is items=None and creating the list inside.

null

A reference pointing at nothing. Dereferencing it is the single most common run time failure in these languages, and its inventor called it his billion dollar mistake.

Modern answers: Optional in Java, nullable types in Kotlin and C# where the compiler forces a check, and Option in Rust where there is no null at all.

What a variable actually holds