Java is pass by value - always, both for primitives and objects.
In the case of objects, the thing that's passed is the reference to the object that lives out on the heap. A method cannot change what that reference points to when it's passed in.
If that reference points to an object that has mutable data, the method can alter its state.
From "The Java Programming Language Second Edition", by Ken Arnold and James Gosling (ISBN 0-201-31006-6 ) (probably from page 40--don't have the book handy right now):
Some people will say incorrectly that objects in Java are "pass by
reference." The term pass by reference properly means that when an
argument is passed to a function, the invoked function gets a
reference to the original value, not a copy of its value. If the
function modifies its parameter, the value in the calling code will be
changed because the argument and parameter use the same slot in
memory. [...] There is exactly one ParameterPassing mode in Java--pass
by value--and that helps keep things simple.
So let's look at your example (with some improvements):
public class Dog {
private String name;
public static void main(String [] args) {
Dog myDog = new Dog("Rover");
System.out.println("before foo: " + myDog);
foo(myDog);
System.out.println("after foo: " + myDog);
}
public static void foo(Dog someDog) {
someDog.setName("Max"); // AAA
someDog = new Dog("Fifi"); // BBB
someDog.setName("Rowlf"); // CCC
}
public Dog(String n) { this.name = n; }
public String getName() { return this.name; }
public void setName(String n) { this.name = n; }
public String toString() { return this.name; }
}
Here's the output:
before foo: Rover
after foo: Max
Tool completed successfully
You can't change what the reference that's passed to foo
points to, so setting it to the reference with the name "Fifi" at line BBB, and subsequently changing the name of that object at line CCC, does nothing. That instance is eligible for garbage collection when foo
exits.
The incoming reference that points to "Rover" has a mutable data member: its name. Changing its value at line AAA is reflected in the reference that was passed in; hence the different output.