Java - Embed a deep and shallow copy of an array

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:

  • Shallow copy:

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: Invalid copy

  • Deep copy:

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: Deep copy

As you can see, the result of the main method is different from the logic of the above scheme.

Any explanation would be appreciated.

+7
java arrays deep-copy shallow-copy
source share
3 answers

I am trying to understand the concept of shallow and deep copy in Java.

In Java, you go through and store references to objects, not the objects themselves.
Therefore, when you have a NameValue[] array , the array does not contain NameValue objects, but object references.
Therefore, when you make a shallow copy in NameValue[] array2 , it means that you simply copy the links from one array to another. This actually means that now both array and array2 refer to exactly the same objects, and any change you make from array[2] will be visible from array2[2] (the same object).

When you make deep copies, you completely copy each object to a different area of ​​memory and store the link to this new object in your new array. Thus, 2 arrays now refer to different objects, and any change to array[2] not visible from array2[2]

Update:
This does not apply to primitives that retain the actual value, not the link.
Thus, when copying int[] a , you get a copy of the values ​​(i.e., a Deep copy in a sense), because a[2] contains the value itself, and not a reference to the value.

+4
source share

I do not know where you read that copyOf() does a deep copy, because it is simply wrong.

Quoting javadoc Arrays.copyOf(T[] original, int newLength) :

For all indices that are valid both in the original array and in the copy , the two arrays will contain the same values .

This means that it is a shallow copy. To be a deep copy, the values ​​would have to point to different objects, since the reference object would also have to be a copy.

To make a deep copy, you need to iterate through the array and copy the values. Java cannot do this for you because it does not know how to copy an object.

eg. how does Java know how to copy a NameValue object? clone() ? Copy constructor? Serialization + deserialization? Factory method? Other means?

+5
source share

I think there is a slight misunderstanding that Arrays.copyOf() creates a deep copy.

Arrays.copyOf() creates a new array containing the old refrences for objects that are not copied, and since the added reference explains in the case of nested arrays, they will not be copied and therefore cannot be considered a deep copy, but a shallow copy.

See more details.

+1
source share

All Articles