Java Pass-by-Value Semantics

Java always passes arguments by value. For objects, the copied value is a reference to the same object, so a method can mutate that object but cannot replace the caller’s reference.

For a primitive argument, Java copies the primitive value into the parameter. Changes to the parameter therefore do not change the caller’s variable.

For an object argument, Java copies the reference value. The parameter and the caller’s variable initially refer to the same object, so mutations through the parameter are visible through the caller’s reference.

Assigning a new object to the parameter is different from mutating the existing object. The parameter then refers to the new object, while the caller’s variable still contains its original reference.

This distinction explains why Java is described as pass-by-value rather than pass-by-reference. The value being copied can itself be an object reference.

Key points

Interview questions

Is Java pass-by-value or pass-by-reference?

Java is strictly pass-by-value. Every method argument is copied into its parameter. When the argument is an object, the copied value is an object reference, so both the caller and method can refer to the same object. This can look like pass-by-reference when the method mutates that object, but the caller’s reference itself is not passed by reference.

Why can a method modify an object passed to it if Java is pass-by-value?

The method receives a copy of the object reference. The copied reference still identifies the same object as the caller’s reference. Therefore, operations that mutate that object are visible through the caller’s reference. The copied reference itself remains independent from the caller’s variable.

What is the difference between mutating an object and reassigning an object parameter?

Mutation changes the state of the object that both references currently identify, so the caller can observe the change. Reassignment changes only the local parameter so it points to another object. The caller’s reference continues pointing to the original object. This distinction is the key to understanding Java’s object argument semantics.

Does `final` make an object parameter immutable?

No. A `final` parameter cannot be assigned a different reference after initialization, but the object it references may still be mutable. For example, a `final StringBuilder` parameter cannot point to a new `StringBuilder`, but its `append` method can still modify the existing builder. Immutability depends on the object’s design, not merely on whether its reference is final.

Can a Java method change which object a caller’s variable refers to?

Not by directly reassigning the method parameter. The parameter contains a copied reference value, so assigning another reference changes only that local copy. A method can indirectly cause a caller to use a different object if it mutates shared state, returns a new reference, or changes a mutable holder whose contents the caller reads. Returning the new object is the conventional direct way to communicate a replacement reference.