Complete the Arrays of objects exercises before reviewing the solutions.
Review the Arrays of objects exercise 1 solution with AP CS Tutor Brandon Horn.
Original code
Coordinate2D[] coors = new Coordinate2D[3];
coors[0] = new Coordinate2D(1, 1);
coors[1] = new Coordinate2D(2, 2);
coors[2] = new Coordinate2D(3, 3);
System.out.println(Arrays.toString(coors));
// prints: [(1, 1), (2, 2), (3, 3)]
Coordinate2D[] coors2 = new Coordinate2D[3];
for(int i = 0; i < coors2.length; i++)
coors2[i] = coors[i];
coors2[0] = new Coordinate2D(4, 4);
coors2[1].setX(5);
coors2[1].setY(5);
System.out.println(Arrays.toString(coors));
System.out.println(Arrays.toString(coors2));
Output
[(1, 1), (2, 2), (3, 3)]
[(1, 1), (5, 5), (3, 3)]
[(4, 4), (5, 5), (3, 3)]
Explanation
An array of objects is really an array of references (memory addresses). (More generally, an array is a bunch of values of the same type stored in sequential memory locations.)
The statement coors2[i] = coors[i]; copies the memory address stored at coors[i] into coors2[i]. It does not copy the object to which coors[i] refers.
At the end of the for loop, both coors and coors2 refer to the same 3 objects. The Coordinate2D objects themselves are neither copied nor changed. This is known as creating a shallow copy of the array.
The statement coors2[0] = new Coordinate2D(4, 4); creates a new Coordinate2D object representing (4, 4) and stores its memory address in coors2[0]. This has no effect on coors, coors[0], or the object to which coors[0] refers.
The statements coors2[1].setX(5); and coors2[1].setY(5); run the mutator methods setX and setY on the object to which coors2[1] refers. coors[i] refers to the same object. The values being changed are those of the instance variables x and y inside the object. The values of coors2[1] and coors[1] (the memory address of the object) remain unchanged.
Step by step memory diagram
Step 1
Coordinate2D[] coors = new Coordinate2D[3];
coors[0] = new Coordinate2D(1, 1);
coors[1] = new Coordinate2D(2, 2);
coors[2] = new Coordinate2D(3, 3);
System.out.println(Arrays.toString(coors));
// prints: [(1, 1), (2, 2), (3, 3)]
Coordinate2D[] coors2 = new Coordinate2D[3];
// additional code not yet run
Memory diagram after Step 1

The default value for elements of an array of objects (really an array of memory addresses) is null.
Output after Step 1
[(1, 1), (2, 2), (3, 3)]
Step 2
Coordinate2D[] coors = new Coordinate2D[3];
coors[0] = new Coordinate2D(1, 1);
coors[1] = new Coordinate2D(2, 2);
coors[2] = new Coordinate2D(3, 3);
System.out.println(Arrays.toString(coors));
// prints: [(1, 1), (2, 2), (3, 3)]
Coordinate2D[] coors2 = new Coordinate2D[3];
for(int i = 0; i < coors2.length; i++)
coors2[i] = coors[i];
// additional code not yet run
Memory diagram after Step 2

The statement coors2[i] = coors[i]; copies the memory address stored at coors[i] into coors2[i]. It does not copy the object to which coors[i] refers.
At the end of the for loop, both coors and coors2 refer to the same 3 objects. The Coordinate2D objects themselves are neither copied nor changed. This is known as creating a shallow copy of the array.
Step 3
Coordinate2D[] coors = new Coordinate2D[3];
coors[0] = new Coordinate2D(1, 1);
coors[1] = new Coordinate2D(2, 2);
coors[2] = new Coordinate2D(3, 3);
System.out.println(Arrays.toString(coors));
// prints: [(1, 1), (2, 2), (3, 3)]
Coordinate2D[] coors2 = new Coordinate2D[3];
for(int i = 0; i < coors2.length; i++)
coors2[i] = coors[i];
coors2[0] = new Coordinate2D(4, 4);
// additional code not yet run
Memory diagram after Step 3

The statement coors2[0] = new Coordinate2D(4, 4); creates a new Coordinate2D object representing (4, 4) and stores its memory address in coors2[0]. This has no effect on coors, coors[0], or the object to which coors[0] refers.
Step 4
Coordinate2D[] coors = new Coordinate2D[3];
coors[0] = new Coordinate2D(1, 1);
coors[1] = new Coordinate2D(2, 2);
coors[2] = new Coordinate2D(3, 3);
System.out.println(Arrays.toString(coors));
// prints: [(1, 1), (2, 2), (3, 3)]
Coordinate2D[] coors2 = new Coordinate2D[3];
for(int i = 0; i < coors2.length; i++)
coors2[i] = coors[i];
coors2[0] = new Coordinate2D(4, 4);
coors2[1].setX(5);
coors2[1].setY(5);
System.out.println(Arrays.toString(coors));
System.out.println(Arrays.toString(coors2));
Memory diagram after Step 4

The statements coors2[1].setX(5); and coors2[1].setY(5); run the mutator methods setX and setY on the object to which coors2[1] refers. coors[i] refers to the same object. The values being changed are those of the instance variables x and y inside the object. The values of coors2[1] and coors[1] (the memory address of the object) remain unchanged.
Output after Step 4
[(1, 1), (2, 2), (3, 3)]
[(1, 1), (5, 5), (3, 3)]
[(4, 4), (5, 5), (3, 3)]