3.6 - Methods: Passing and Returning References of an Object
When the argument is an object reference instead of a primitive, the parameter gets a copy of that reference, meaning it points to the same object, not a brand new independent copy. So if that object is mutable, the method actually can change its state, and that change sticks around after the method finishes.
public void renameDog(Dog d) { d.setName("Buddy"); // this actually changes the original dog object } Dog myDog = new Dog("Rex", 3); renameDog(myDog); System.out.println(myDog.getName()); // "Buddy", it really did change
The parameter is still only a copy of the reference, though. If the method points the parameter at a different object, the caller’s variable doesn’t change:
public void replaceDog(Dog d) { d = new Dog("Buddy", 5); // d now points to a new object, myDog doesn't } Dog myDog = new Dog("Rex", 3); replaceDog(myDog); System.out.println(myDog.getName()); // "Rex", the original object was never touched
Same idea with strings:
String objects are immutable (see 1.15), so a method can never change a String passed to it. The most it can do is point its own parameter at a different String.Good practice: avoid modifying an object passed in as a parameter unless the task actually requires it.
If a method returns an object reference, it returns the actual reference, not a new copy of the object.
For example,
getPet below hands back the Owner’s actual Dog, so changing it through the returned reference changes the Owner’s dog too:public class Owner { private Dog pet; public Owner(String petName, int petAge) { pet = new Dog(petName, petAge); } public Dog getPet() { return pet; // returns a reference to the Owner's Dog, not a copy } } Owner sam = new Owner("Rex", 3); Dog p = sam.getPet(); // p and sam's pet are now the same object p.setName("Max"); System.out.println(sam.getPet().getName()); // Max, sam's dog really changed
So returning a reference to a mutable object lets outside code change your object’s private data. If that’s a problem, have the method build and return a new
Dog with the same name and age instead, just like the constructor copy in 3.4.One more rule: a method can’t reach into the private data or private methods of a parameter unless that parameter is the same type as the class the method is written in.
public class Dog { private String name; public boolean sameNameAs(Dog other) { return this.name.equals(other.name); // allowed! other is also type Dog } }
If the parameter is a different class, the method has to use that class’s
public methods instead:public class Owner { private Dog pet; public boolean petHasSameName(Dog other) { // other.name won't compile here: this is the Owner class, so Dog's private data is off limits return pet.getName().equals(other.getName()); // use Dog's public methods instead } }