Unit 3 · 20 min
3.6 Methods: Passing and Returning References of an Object
One object, two arrows: whatever you do to the object through one arrow, the other arrow sees.
Summary, objectives and course and exam description (CED) codes
Java always passes arguments by value; when the argument is an object reference, the value copied is the reference, so the parameter and the argument refer to the same object. A method can use that reference to change a mutable object, and returning an object returns the reference, not a new copy. A method can use the private data of a parameter only when the parameter's type is the method's own class.
By the end of this session you can
- 3.6.A Develop code to define behaviors of an object through methods written in a class using object references, and determine the result of calling these methods.
Reviewed against the CED on
1LearnThe notes, the traps and how to remember them
1. Passing an object: the reference is copied
Java passes arguments by value (the AP® term is call by value): the parameter is initialized with a copy of the value stored in the argument. For an object, the variable stores a reference, so the parameter gets a copy of that reference. It does not create a new, independent copy of the object 3.6.A.1. The parameter and the argument now refer to the same object. Two references to one object are called aliases.
If the object is mutable, the method can use its reference to change the object’s state 3.6.A.1.
This class is used on the whole page:
public class BankAccount
{
private String owner;
private int balance;
public BankAccount(String name, int start)
{
owner = name;
balance = start;
}
public String getOwner()
{
return owner;
}
public int getBalance()
{
return balance;
}
public void deposit(int amount)
{
balance += amount;
}
/** Returns true if this account has a larger balance than other */
public boolean hasMoreThan(BankAccount other)
{
return balance > other.balance;
}
/** Moves amount from this account to other */
public void transferTo(BankAccount other, int amount)
{
balance -= amount;
other.balance += amount;
}
public String toString()
{
return owner + ": " + balance;
}
}
A method in another class receives an account and adds 10 percent interest:
public class Bank
{
public static void addInterest(BankAccount acct)
{
acct.deposit(acct.getBalance() / 10);
}
}
BankAccount mine = new BankAccount("Rosa", 200);
Bank.addInterest(mine);
System.out.println(mine);
Output:
Rosa: 220
During the call, memory looks like this:
mine (caller) [ ref ] ---+
+---> BankAccount object: owner "Rosa", balance 200 -> 220
acct (parameter) [ ref ] ---+
Only one BankAccount object exists (println shows it through its toString method; writing toString is background, not tested on the AP® exam). acct.deposit(...) changed it, and mine sees the change.
2. Reassigning the parameter does not change the caller
Because the reference was copied, giving the parameter a new object only changes the method’s copy. The caller’s variable still refers to the original object.
public class Bank
{
public static void replace(BankAccount acct)
{
acct = new BankAccount("Temp", 0);
acct.deposit(5);
}
}
BankAccount mine = new BankAccount("Rosa", 200);
Bank.replace(mine);
System.out.println(mine);
Output:
Rosa: 200
mine (caller) [ ref ] ---> BankAccount: owner "Rosa", balance 200 (untouched)
acct (parameter) [ ref ] ---> BankAccount: owner "Temp", balance 5 (gone after the call)
| Inside the method | Does the caller see a change? |
|---|---|
acct.deposit(5); (call a mutator through the parameter) |
Yes: same object |
acct = new BankAccount("Temp", 0); (reassign the parameter) |
No: only the copy of the reference moved |
Watch out: a String parameter is a reference too, but String objects are immutable. No method can change the caller’s string; methods like substring return a new string instead.
3. Do not change parameters unless the specification says so
It is good programming practice not to modify mutable objects that are passed as parameters, unless the specification requires it 3.6.A.1. The caller does not expect a method that only “calculates” something to change their object.
This method counts how many monthly deposits it takes to reach a goal. The first version is wrong: it deposits into the caller’s real account while it counts.
public class Planner
{
// BAD: changes the account it was given
public static int monthsToGoal(BankAccount acct, int goal, int monthly)
{
int months = 0;
while (acct.getBalance() < goal)
{
acct.deposit(monthly);
months++;
}
return months;
}
}
BankAccount savings = new BankAccount("Rosa", 100);
System.out.println(Planner.monthsToGoal(savings, 250, 50));
System.out.println(savings);
Output:
3
Rosa: 250
The good version copies the balance into a local int and leaves the object alone:
public class Planner
{
// GOOD: reads the account but does not change it
public static int monthsToGoal(BankAccount acct, int goal, int monthly)
{
int balance = acct.getBalance();
int months = 0;
while (balance < goal)
{
balance += monthly;
months++;
}
return months;
}
}
BankAccount savings = new BankAccount("Rosa", 100);
System.out.println(Planner.monthsToGoal(savings, 250, 50));
System.out.println(savings);
Output:
3
Rosa: 100
4. Returning a reference
When the return expression evaluates to an object reference, the reference is returned, not a reference to a new copy of the object 3.6.A.2. The caller then holds an alias to the object stored inside the class.
public class Club
{
private String name;
private BankAccount treasury;
public Club(String clubName, int startMoney)
{
name = clubName;
treasury = new BankAccount(clubName, startMoney);
}
/** Returns the club's own account (an alias) */
public BankAccount getTreasury()
{
return treasury;
}
/** Returns a new account with the same values (a copy) */
public BankAccount getTreasuryCopy()
{
return new BankAccount(treasury.getOwner(), treasury.getBalance());
}
public int funds()
{
return treasury.getBalance();
}
}
Club chess = new Club("Chess", 500);
BankAccount a = chess.getTreasury();
a.deposit(100);
System.out.println(chess.funds());
BankAccount b = chess.getTreasuryCopy();
b.deposit(1000);
System.out.println(chess.funds());
Output:
600
600
a refers to the club’s real account, so the deposit through a changed the club. b refers to a new object, so the deposit through b did not.
5. Private access through a parameter of the same class
Methods cannot access the private data and private methods of a parameter that refers to an object, unless the parameter is the same type as the method’s enclosing class 3.6.A.3.
That is why hasMoreThan and transferTo in BankAccount can use other.balance directly: other is a BankAccount, and the code is inside BankAccount.
BankAccount x = new BankAccount("Rosa", 300);
BankAccount y = new BankAccount("Theo", 120);
x.transferTo(y, 50);
System.out.println(x + ", " + y);
System.out.println(x.hasMoreThan(y));
Output:
Rosa: 250, Theo: 170
true
The same expression in a different class does not compile:
public class Auditor
{
public static boolean isNegative(BankAccount acct)
{
return acct.balance < 0;
}
}
Compiler says:
error: balance has private access in BankAccount
The fix is to use the public accessor: return acct.getBalance() < 0;.
Watch out: transferTo changes its parameter other on purpose. That is fine because moving money into the other account is exactly what the method’s specification says it does 3.6.A.1.
Lock it in: memory hooks
- Pass by valueJava always copies the value in the variable. For objects, that value is an arrow (a reference), so you get a second arrow to the same object.
- Change vs reassignparam.mutator() changes the shared object. param = new Thing() only moves the method's own arrow.
- Private accessSame class, same keys: a BankAccount method can open another BankAccount's private data.
Common misconceptions
"Java passes objects by reference, so a method can make the caller's variable point to a different object."
Not quite. Java passes by value. For an object the value is a copy of the reference. The method can change the object through it, but assigning a new object to the parameter changes only the parameter, never the caller's variable.
"Passing an object to a method gives the method its own copy of the object."
Not quite. No new object is created. The parameter and the argument are aliases: two references to one object.
"An accessor that returns an object returns a safe copy."
Not quite. Returning an object reference returns the reference itself. The caller can use it to change the object inside your class, unless you return a new copy on purpose.
Exam traps
- A void method that calls a mutator on its object parameter does change the caller's object.
- A method that sets its parameter to a new object does not change the caller's object.
- Strings are immutable: a method can never change the caller's String, even though it receives a reference to it.
- other.balance compiles inside the BankAccount class but not inside any other class.
2PracticeRecall it, then check yourself
In 30 seconds
- An object reference argument: the parameter gets a copy of the reference, not a copy of the object.
- Parameter and argument are aliases, so a mutator called through the parameter changes the caller's object.
- Assigning a new object to the parameter does not change the caller's variable.
- Do not modify mutable objects passed as parameters unless the specification requires it.
- Returning an object returns the reference, not a new copy of the object.
- A method can reach a parameter's private data only if the parameter is the same type as the method's class.
Cover this list, say the points out loud, then take the checkpoint without scrolling back up.
Checkpoint · 5 questions
Checkpoint: Methods: Passing and Returning References of an Object
Pick an answer to mark it. Every answer is explained, and you can try any question again. Your saved score counts first tries only, and stays in this browser.
3PrevailLock it in for exam day
By the numbers
- Things that are copied when objects go in and out of methods two things CED 3.6.A.1, 3.6.A.2
- When a method may use a parameter's private data and methods one case CED 3.6.A.3
Key terms: flip the cards
Read the term, say the definition out loud, then flip to check. Struggling a little to remember is what makes it stick.
-
Passing referencestap to flip
When an argument is an object reference, the parameter gets a copy of the reference, so both refer to the same object.
Example and CED codes -
Aliasingtap to flip
Two or more references that refer to the same object, so a change made through one reference is seen through the others.
Example and CED codes -
Call by valuetap to flip
The way Java passes arguments: each parameter is initialized with a copy of the argument.
Example and CED codes -
Object referencetap to flip
The value a reference variable holds: it can be thought of as the memory address of the object.
Example and CED codes -
Parametertap to flip
A variable declared in the header of a method or constructor. It receives the value passed in and can be used in the body.
Example and CED codes -
Argumenttap to flip
A value passed into a method or constructor when it is called.
Example and CED codes -
nulltap to flip
A special literal meaning a reference variable is not associated with any object.
Example and CED codes -
Encapsulationtap to flip
Keeping the implementation details of a class hidden from other classes, mainly by making instance variables private.
Example and CED codes
Questions students ask
Is Java pass by value or pass by reference?
Java is always pass by value. When the argument is an object, the value that is copied is the reference, so the method can change the object but cannot make the caller's variable refer to a different object.
Why did my object change after I passed it to a method?
The parameter received a copy of the reference, so it refers to the same object as your variable. If the method called a mutator through the parameter, the one shared object changed.
Can a method access the private variables of another object?
Only if that object's type is the same class the method is written in. A BankAccount method can read other.balance when other is a BankAccount; a method in a different class cannot.
What is aliasing in Java?
Aliasing happens when two references refer to the same object. Changes made through one reference are visible through the other.