I am trying to understand the concept of shallow and deep copy in Java. There are many articles and questions and answers about this subject, but whenever I try to implement these concepts in real Java code, everything becomes unclear to me.
One of the answers on which I base my understanding is in this link , where deep and shallow copying is explained using schemas.
I will show you below my implementation for each case:
I took the System.arraycopy () method for my example, since in many articles I read that it performs a shallow copy (along with the clone method)
public class Test { public static void main(String[] args) { NameValue[] instance1 = { new NameValue("name1", 1), new NameValue("name2", 2), new NameValue("name3", 3), }; NameValue[] instance2 = new NameValue[instance1.length]; // Print initial state System.out.println("Arrays before shallow copy:"); System.out.println("Instance 1: " + Arrays.toString(instance1)); System.out.println("Instance 2: " + Arrays.toString(instance2)); // Perform shallow copy System.arraycopy(instance1, 0, instance2, 0, 3); // Change instance 1 for (int i = 0; i < 3; i++) { instance1[i].change(); } // Print final state System.out.println("Arrays after shallow copy:"); System.out.println("Instance 1: " + Arrays.toString(instance1)); System.out.println("Instance 2: " + Arrays.toString(instance2)); } private static class NameValue { private String name; private int value; public NameValue(String name, int value) { super(); this.name = name; this.value = value; } public void change() { this.name = this.name + "-bis"; this.value = this.value + 1; } @Override public String toString() { return this.name + ": " + this.value; } } }
The result of the basic methods is as follows:
Arrays before shallow copy: Instance 1: [name1: 1, name2: 2, name3: 3] Instance 2: [null, null, null] Arrays after shallow copy: Instance 1: [name1-bis: 2, name2-bis: 3, name3-bis: 4] Instance 2: [name1-bis: 2, name2-bis: 3, name3-bis: 4]
this result matches the pattern of the previous link: 
I took the Arrays.copyOf () method for this example, because in many articles I read that it performs a deep copy (along with the Arrays.copyOfRange method)
public static void main(String[] args) { NameValue[] instance1 = { new NameValue("name1", 1), new NameValue("name2", 2), new NameValue("name3", 3), }; NameValue[] instance2 = new NameValue[instance1.length]; // Print initial state System.out.println("Arrays before deep copy:"); System.out.println("Instance 1: " + Arrays.toString(instance1)); System.out.println("Instance 2: " + Arrays.toString(instance2)); // Perform deep copy instance2 = Arrays.copyOf(instance1, 3); // Change instance 1 for (int i = 0; i < 3; i++) { instance2[i].change(); } // Print final state System.out.println("Arrays after deep copy:"); System.out.println("Instance 1: " + Arrays.toString(instance1)); System.out.println("Instance 2: " + Arrays.toString(instance2)); }
which displays:
Arrays before deep copy: Instance 1: [name1: 1, name2: 2, name3: 3] Instance 2: [null, null, null] Arrays after deep copy: Instance 1: [name1-bis: 2, name2-bis: 3, name3-bis: 4] Instance 2: [name1-bis: 2, name2-bis: 3, name3-bis: 4]
If we base deep copy logic on the previous diagram, this should be the result: 
As you can see, the result of the main method is different from the logic of the above scheme.
Any explanation would be appreciated.