Skip to main content

Unit 3 · Topic 3.6

3.6 Methods: Passing and Returning References of an Object

When an object is passed to a method or returned from one, what moves around is a reference, not a copy of the object. This topic shows exactly what a method can and can't change through a reference, and when a method may use another object's private data.

Key terms

  • object reference
  • pass by value
  • mutable object
  • returning a reference

Passing a reference

When the argument is an object, the parameter gets a copy of the reference. The method doesn't get its own copy of the object. Both the caller's variable and the parameter point to the same object.

That has two consequences, and you need both:

  • If the method calls a mutator on the parameter, the original object changes, and the caller sees the change.
  • If the method assigns a new object to the parameter, only the parameter changes. The caller's variable still refers to the original object.

Seeing both cases

public static void reset(Account a) { a = new Account(0); } public static void drain(Account a) { a.transferTo(new Account(0), a.getBalance()); }

Here reset points its own parameter at a new account and then ends, so the caller's account is untouched. drain uses the reference to move all the money out, so the caller's account really does change.

Good practice is not to change a mutable object passed in as a parameter unless the method's description says to.

Draw it out

For tracing questions, draw each object as a box with its instance variables inside, and each variable as a small box with an arrow pointing to an object. Passing an object to a method draws a new arrow from the parameter to the same box. Calling a mutator changes what's written inside a box. Assigning a new object to a variable moves only that variable's arrow. When the method ends, its parameter arrows disappear, but every change made inside the boxes stays.

Returning a reference

When a method returns an object, it returns a reference to it, not a new copy. If a getter returns a reference to a mutable instance variable, the caller can use it to change that object's state from outside the class.

Private access within the same class

Normally you can't touch another object's private instance variables. There's one exception: inside a class's own code, you can use the private data and methods of any parameter whose type is that same class. Encapsulation works class by class, not object by object.

public class Account { private int balance; public Account(int start) { balance = start; } public void transferTo(Account other, int amount) { balance -= amount; other.balance += amount; } public int getBalance() { return balance; } }

transferTo can write other.balance because other is also an Account. A method in some other class couldn't.

Worked examples

Try each one yourself first, then open the solution.

  1. Example 1

    Changing an object through a parameter

    Using the Account class above, what does this code print?Account mine = new Account(100); Account yours = new Account(20); mine.transferTo(yours, 30); System.out.println(mine.getBalance() + " " + yours.getBalance());

    Show the solution
    1. Step 1: mine starts with 100 and yours with 20.
    2. Step 2: mine.transferTo(yours, 30) runs with balance meaning mine's balance and other referring to the same object as yours.
    3. Step 3: mine's balance becomes 70. other.balance += 30 changes the object yours refers to, so its balance becomes 50.

    Answer: It prints 70 50.

  2. Example 2

    Reassigning versus mutating

    Using the methods reset and drain shown above, what does this code print?Account acct = new Account(40); reset(acct); System.out.println(acct.getBalance()); drain(acct); System.out.println(acct.getBalance());

    Show the solution
    1. Step 1: reset(acct): the parameter a starts as a copy of acct's reference. Then a = new Account(0) points a at a different object. acct still refers to the original account, which still holds 40.
    2. Step 2: drain(acct): a refers to the same account as acct, and a.transferTo(...) moves all 40 out of it. That changes the original object.

    Answer: Two lines: 40, then 0.

  3. Example 3

    Returning a reference

    Using Account from above, Team returns its own private account:public class Team { private Account fund; public Team() { fund = new Account(500); } public Account getFund() { return fund; } }What does this code print?Team t = new Team(); Account f = t.getFund(); f.transferTo(new Account(0), 200); System.out.println(t.getFund().getBalance());

    Show the solution
    1. Step 1: getFund() returns a reference to the team's own Account object, not a copy.
    2. Step 2: f and the team's fund now refer to the same account.
    3. Step 3: Transferring 200 out through f changes that shared account to 300, so the team's fund is 300.

    Answer: It prints 300.

Common mistakes

  • Thinking a method gets its own copy of an object argument. It gets a copy of the reference, so both refer to one object.
  • Thinking that assigning a new object to a parameter changes the caller's variable. It doesn't.
  • Thinking a getter that returns an object hands back a safe copy. It returns a reference to the same object.

On the exam

  • Tracing questions often pass an object to a method that both mutates it and reassigns the parameter. Draw a box for each object and arrows for each variable, and move only the arrows when a variable is reassigned.

Connected topics

Videos

Check yourself

4 questions on 3.6 Methods: Passing and Returning References of an Object. Pick an answer to see if you got it, and why.

Code
public class Box
{
    private int value;
 
    public Box(int v)
    {
        value = v;
    }
 
    public int getValue()
    {
        return value;
    }
 
    public void setValue(int v)
    {
        value = v;
    }
}
Question 1 of 4

Consider the following methods, which appear in a class other than Box.public static void reset(Box b) { b.setValue(0); } public static void replace(Box b) { b = new Box(99); }What is printed as a result of executing the following code segment, which appears in the same class as reset and replace?Box a = new Box(5); replace(a); System.out.print(a.getValue() + " "); reset(a); System.out.print(a.getValue());

Question 2 of 4

Consider the following methods, which appear in a class other than Box.public static void swapRefs(Box a, Box b) { Box temp = a; a = b; b = temp; } public static void swapValues(Box a, Box b) { int temp = a.getValue(); a.setValue(b.getValue()); b.setValue(temp); }What is printed as a result of executing the following code segment, which appears in the same class as the two methods?Box x = new Box(1); Box y = new Box(2); swapRefs(x, y); System.out.print(x.getValue() + " " + y.getValue() + " "); swapValues(x, y); System.out.print(x.getValue() + " " + y.getValue());

Question 3 of 4

Consider the following classes.public class Player { private int number; public Player(int n) { number = n; } public int getNumber() { return number; } public void setNumber(int n) { number = n; } } public class Team { private Player captain; public Team(int captainNumber) { captain = new Player(captainNumber); } public Player getCaptain() { return captain; } }What is printed as a result of executing the following code segment?Team t = new Team(10); Player p = t.getCaptain(); p.setNumber(7); System.out.println(t.getCaptain().getNumber());

Question 4 of 4

Consider the following class.public class Money { private int cents; public Money(int c) { cents = c; } public int getCents() { return cents; } public boolean moreThan(Money other) { return cents > other.cents; } }A different class, Wallet, has a method with a parameter Money m. Wallet doesn't declare any variable named cents. Which of the following statements compiles if it appears in that Wallet method?

0 of 4 answered