Complete the Primitive types vs references exercises with calls before reviewing the solutions.

Review the primitive exercise solution with AP CS Tutor Brandon Horn.

Original code

public static void main(String[] args)
{
    Coordinate2D c = new Coordinate2D(1,1);
    reference1(c);
    System.out.println(c);
}

private static void reference1(Coordinate2D d)
{
    d.setX(2);
}

Output

(2, 1)

Explanation

All arguments in Java are passed by value, including references. The call reference1(c); passes a copy of the value of c to the reference1 method. The value of c is the memory address of the object containing x: 1, y: 1.

The reference1 method runs a mutator method on the object to which both c and d point.

Step by step with memory diagrams

Step 1

public static void main(String[] args)
{
    Coordinate2D c = new Coordinate2D(1,1);
    // more code not yet run
}

Memory diagram after Step 1

diagram showing c pointing to a box containing x and y, each with value 1

Step 2

public static void main(String[] args)
{
    Coordinate2D c = new Coordinate2D(1,1);
    reference1(c);
    // more code not yet run
}

private static void reference1(Coordinate2D d)
{
    // more code not yet run
}

Step 2 is immediately after the call to the reference1 method, but before any code inside the reference1 method has been run.

Memory diagram after Step 2

diagram showing c and d pointing to the same box containing x and y, each with value 1

All arguments in Java are passed by value. The call reference1(c); passes a copy of the value of c as the initial value of the parameter d. The value of c is the memory address of the object containing x: 1, y: 1. In other words, the value of c is the arrow.

Immediately after the call, c and d point to the same object. The object itself is not copied, nor are the instance variables inside.

It is common to confuse pass by reference, which does not exist in Java, with passing a reference.

Step 3

public static void main(String[] args)
{
    Coordinate2D c = new Coordinate2D(1,1);
    reference1(c);
    // more code not yet run
}

private static void reference1(Coordinate2D d)
{
    d.setX(2);
}

Step 3 is immediately after execution of the statement d.setX(2);, but before the reference1 method returns.

Memory diagram after Step 3

diagram showing c and d pointing to the same box containing x with value 2 and y with value 1

d.setX(2); means go to the object to which d points and run the setX method. This changes the value of x inside the object to which both c and d point. The values of c and d themselves, the memory address of the object, are unchanged.

Step 4

public static void main(String[] args)
{
    Coordinate2D c = new Coordinate2D(1,1);
    reference1(c);
    System.out.println(c);
}

private static void reference1(Coordinate2D d)
{
    d.setX(2);
}

Step 4 is after the reference1 method returns and after the print statement executes.

Memory diagram after Step 4

diagram showing c pointing to a box containing x with value 2 and y with value 1

The scope of parameters is the method in which they are defined. When the reference1 method returns, the variable d no longer exists.

Output after Step 4

(2, 1)

The main method prints c, which runs the toString method on the object to which c refers.

Additional classes & objects resources

Comments

Comment on Primitive types vs references with method calls