It's easiest to illustrate this with code:
public class ValueHolder {
public ValueHolder(int value) { this.value = value; }
public int value;
public static ValueHolder THREE = new ValueHolder(3);
}
public class DoSomething extends TestCase {
public void passByValue(byvalue ValueHolder value) {
value.value = 1;
value = new ValueHolder(2);
}
public void testPassByValue() {
ValueHolder myValue = ValueHolder.THREE;
passByValue(myValue);
assertEquals(ValueHolder.THREE, myValue);
assertEquals(3, myValue.value);
}
public void passByReference(byref ValueHolder value) {
value.value = 1;
value = new ValueHolder(2);
}
public void testPassByReference() {
ValueHolder myValue = ValueHolder.THREE;
passByReference(myValue);
assertNotEquals(ValueHolder.THREE, myValue);
assertEquals(2, myValue.value);
}
public void passReferenceByValue(ValueHolder value) {
value.value = 1;
value = new ValueHolder(2);
}
public void testPassByValue() {
ValueHolder myValue = ValueHolder.THREE;
passByValue(myValue);
assertEquals(ValueHolder.THREE, myValue);
assertEquals(1, myValue.value);
}
}
Syntax is slightly made-up because Java doesn't have true pass-by-value or pass-by-reference for object, only pass-reference-by-value. But the test cases illustrate the expected semantics for each parameter passing mode.In each case, you're passing a mutable object containing a value to the function. In pass-by-value, you pass a completely new copy of the object in, so the mutation doesn't affect the original object at all, and then the reassignment obviously doesn't propagate back to the caller. In pass-by-reference, you pass in a reference, so the mutation changes the object in the caller's scope, and then the assignment reassigns the variable in the caller's scope to the new ValueHolder. It's this last part that pass-reference-by-value can't do: normal Java semantics let you mutate the object passed in, but you can't make the variable in the calling frame actually point to an entirely new object.
Make sense?