# AP® Computer Science A 3.6 Methods: Passing and Returning References of an Object

Source: https://lockincs.com/ap-csa/unit-3/3-6-methods-passing-and-returning-references-of-an-object/  
Last reviewed against the College Board Course and Exam Description (CED): 2026-11-12  
CED codes: 3.6.A, 3.6.A.1, 3.6.A.2, 3.6.A.3

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.

## What you will learn

- 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.

## 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.

## Common mix-ups

- Not true: Java passes objects by reference, so a method can make the caller's variable point to a different object. 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.
- Not true: Passing an object to a method gives the method its own copy of the object. No new object is created. The parameter and the argument are aliases: two references to one object.
- Not true: An accessor that returns an object returns a safe copy. 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.

## 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.

## Checkpoint: 5 practice questions

### Question 1

Consider the following classes. The code segment below the classes appears in a method in another class. What is printed as a result of executing the code segment?

```java
public class Box
{
    private int size;

    public Box(int s)
    {
        size = s;
    }

    public int getSize()
    {
        return size;
    }

    public void grow()
    {
        size++;
    }
}

public class Mover
{
    public static void change(Box b)
    {
        b.grow();
        b = new Box(10);
        b.grow();
    }
}

Box box = new Box(3);
Mover.change(box);
System.out.println(box.getSize());
```

- A. 3
- B. 4
- C. 11
- D. 10

**Answer: B.** `b` starts as a copy of the reference in `box`, so the first `b.grow()` changes the caller's object from 3 to 4. Then `b = new Box(10)` makes only the parameter refer to a new object, and the second `grow` changes that new object to 11, which the caller never sees. The option 3 assumes objects are copied when passed, and 11 assumes the reassignment changes the caller's variable.

### Question 2

Consider the following `Team` class, which uses the `Box` class from the previous question. The code segment below the class appears in a method in another class. What is printed as a result of executing the code segment?

```java
public class Team
{
    private Box gear;

    public Team()
    {
        gear = new Box(5);
    }

    public Box getGear()
    {
        return gear;
    }

    public int gearSize()
    {
        return gear.getSize();
    }
}

Team t = new Team();
Box g = t.getGear();
g.grow();
g.grow();
System.out.println(t.gearSize() + " " + g.getSize());
```

- A. 5 7
- B. 5 5
- C. 7 5
- D. 7 7

**Answer: D.** `getGear` returns the reference stored in `gear`, not a reference to a new copy, so `g` and `gear` refer to the same `Box`. Growing it twice through `g` changes the team's box from 5 to 7, and both expressions report 7. The option 5 7 assumes the accessor returned a copy of the object.

### Question 3

The `Box` class from question 1 has a private instance variable `size` and a public accessor `getSize`. Which of the following methods compiles without error when it replaces `/* missing code */` in the `Shelf` class below?

```java
public class Shelf
{
    /* missing code */
}
```

- A. `public static int total(Box a, Box b) { return a.getSize() + b.getSize(); }`
- B. `public static int total(Box a, Box b) { return a.size + b.size; }`
- C. `public static int total(Box a, Box b) { return size + b.size; }`
- D. `public static int total(Box a, Box b) { return a.size() + b.size(); }`

**Answer: A.** `Shelf` is a different class from `Box`, so it cannot access the private variable `size` of its `Box` parameters and must use the public accessor `getSize`. Using `size` without an object does not compile in `Shelf` either, since `Shelf` has no such variable. `Box` has no method named `size`.

### Question 4

The following method is added inside the `Box` class from question 1. Which of the following best describes the result?

```java
public boolean biggerThan(Box other)
{
    return size > other.size;
}
```

- A. It does not compile, because `size` is private in `other`
- B. It compiles only if the method is declared `static`
- C. It compiles, because `other` is the same type as the enclosing class
- D. It compiles, but it always compares the object with itself

**Answer: C.** A method may use the private data of a parameter when the parameter is the same type as the method's enclosing class. Here the method is in `Box` and `other` is a `Box`, so `other.size` is allowed. `size` alone means the size of the object whose method is called, and `other.size` is the other box's size, so two different objects are compared. A static method could not use `size` without an object at all.

### Question 5

The following method is specified to return a short description of a `Box` from question 1. Which of the following best describes a problem with the method?

```java
/** Returns a description of b */
public static String describe(Box b)
{
    b.grow();
    return "Box of size " + b.getSize();
}
```

- A. It does not compile, because a static method cannot have an object parameter
- B. The call `b.grow()` changes only a copy of the box, so the description is wrong
- C. It changes the caller's box, but the specification only asks for a description
- D. It returns a reference to a new copy of the box instead of a `String`

**Answer: C.** `b` refers to the caller's object, so `b.grow()` changes the caller's box. Good practice is not to modify a mutable object passed as a parameter unless the specification requires it, and this one only asks for a description. Static methods can have object parameters, no copy of the box is made, and the method returns a `String`.

## 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.

---

© LockInCS, licensed CC BY-NC-ND 4.0. AP® is a trademark registered by the College Board, which is not affiliated with, and does not endorse, this website.
