UNIT 3: CLASS CREATION · TOPIC 3.6
3.6 Methods: Passing and Returning References of an Object
When you pass an object to a method, you pass its address. The method can change the object — and the caller sees it. Primitives don't work that way.
What you need to know
- Java passes all arguments by value. For primitives, the value is the number. For objects, the value is the reference — so the parameter and the argument point to the same object.
- A method can modify the object a reference parameter points to (call its mutators, change array elements), and the caller sees the change.
- A method cannot make the caller's variable point to a different object. Reassigning the parameter (
p = new Thing()) only changes the local copy of the reference. - Changing a primitive parameter never affects the caller.
- Returning an object returns its reference. The caller can then modify that object through the returned reference.
- Returning a reference to a private instance variable that is a mutable object breaks encapsulation — outside code can change internal state. Strings are safe because they're immutable.
Worked example
public static void bump(Counter c, int n)
{
c.increment(); // affects the caller's object
n++; // affects only the local n
c = new Counter("other"); // caller's variable still points to original
c.increment(); // this increments the new local object only
}
Counter myC = new Counter("a"); // count 0
int myN = 5;
bump(myC, myN);
System.out.println(myC.getCount()); // 1
System.out.println(myN); // 5
Exam tip: Draw the arrow. Parameter and argument arrows point to the same box; mutating the box is visible to both. Reassigning the parameter moves only the parameter's arrow. Primitives are just copied numbers.
Going deeper
The nuance, edge cases, and connections that turn a 3 into a 5.
- Java is always pass-by-value. The value of a reference variable is an address. So passing an object passes a copy of the address — the parameter points to the same object. The phrase "pass by reference" is misleading in Java; it's pass-by-value where the value is a reference.
- Consequence 1: a method can call mutators on a parameter object and the caller sees the changes.
void bump(Counter c) { c.increment(); }— the caller's Counter is incremented. - Consequence 2: a method cannot replace the caller's object.
c = new Counter();inside the method just repoints the local parameter. The caller's variable still points to the original. - Arrays are objects, so passing an array lets the method modify its elements (
arr[0] = 5is visible to the caller) but not replace the array (arr = new int[10]is not). This is the basis for many Unit 4 questions. - Strings are objects but immutable, so a method receiving a String can't change it — every String method makes a new String, and reassigning the parameter doesn't affect the caller. Strings behave like primitives for practical purposes.
- Returning a reference gives the caller access to the object. If a class returns a reference to its private mutable field (an ArrayList, say), the caller can modify the object's internals — an encapsulation leak. Returning a String or primitive is safe. FRQ 2 sometimes asks you to return a copy for this reason.
- Draw it. Boxes for objects, arrows for every variable and parameter. Mutation = change inside a box (visible everywhere). Reassignment = move one arrow (visible only there).
Mistakes that cost points
- Expecting reassignment to propagate.
param = new Thing()changes only the parameter. - Expecting a primitive parameter to change the caller. Never.
- Thinking a String parameter can be modified. Immutable. Reassigning it locally does nothing to the caller.
- Forgetting that array elements are shared. Modifying
arr[i]in a method changes the caller's array.
Practice questions
Written in the style of the real exam. Try each one before revealing the answer.
Q1 Consider the following method, where
Score has a mutator add(int p) and accessor getPoints().
public static void update(Score s, int pts)
{
s.add(pts);
pts = 0;
}After Score sc = new Score(); int p = 10; update(sc, p);, what are sc.getPoints() and p?Show answer
Answer: B. s and sc share the object, so add(10) is visible: 10 points. pts is a local copy; setting it to 0 doesn't change p.
Q2 Consider the following.
public static void reset(Counter c)
{
c = new Counter("new");
}
Counter x = new Counter("old");
x.increment();
reset(x);
System.out.println(x.getCount());What is printed?Show answer
Answer: B. reset only reassigns its local parameter. x still points to the original object with count 1.
Key vocabulary
- Pass by value
- Java copies the argument's value; for objects that value is a reference
- Reference parameter
- a parameter that holds the address of the caller's object