There seems to be a lot of confusion and different opinions on this out there ([1] and other sources) on whether Arrays.copyOf
will produce a deep or shallow copy.
This test suggests that the copy is deep:
String[] sourceArray = new String[] { "Foo" };
String[] targetArray = java.util.Arrays.copyOf( sourceArray, 1 );
sourceArray[0] = "Bar";
assertThat( targetArray[0] ).isEqualTo( "Foo" ); // passes
This test suggests that the copy is shallow:
String[][] sourceArray = new String[][] { new String[] { "Foo" } };
String[][] targetArray = java.util.Arrays.copyOf( sourceArray, 1 );
sourceArray[0][0] = "Bar";
assertThat( targetArray[0][0] ).isEqualTo( "Foo" ); // fails
Is the solution simply that a deep copy of the top-level dimension is made, but other dimensions are a shallow copy? What is the truth?
It produces a shallow copy, i.e. a new array that contains "old" references (to the same objects, those are not being copied).
In particular, if you have nested arrays, those will not be copied. You will just get a new array whose "top level" points to the same "second level" arrays as the original did. Any changes inside those nested arrays will be reflected in both copy and original.
No, it does not. When you assign a new object to the "original" array, this does not affect the copy. It is, after all, a copy.
This is the same situation as:
No "deep copy" here.
'Shallow' or 'deep' - and this is a matter that I see no one defining precisely - the method
Arrays.copyOf(..)
DOES in practice produce a copy of the source array which remains unaffected by changes to the source array.Take the following simple example with int arrays:
In practice, when people seek a "deep copy" of an array, they merely want something that is unaffected by changes to the original.
And this Arrays.copyOf(..)` method does give them this.
As well as primitive type arrays, String object arrays also behave as the above example, giving output like :
when the initial source array entries are concatenated by "1".
It also 'works' for Object arrays in the sense that the target is no longer tied to the source when the latter is reassigned. BUT looking at the output for the first element of both arrays after copying and then after altering source[0] reveals the full truth :
After the original source array is copied, the target elements simply have been pointed to whatever values are currently held in their source counterparts. For target[0] it is the contents of memory address 1db9742 -- which is also the the same memory address holding source[0] . . . .
And the reason we get a debonding between source and target after source[0] is reassigned is due to the fact that the assignment statement
simply causes the memory reference held in source[0] to be changed to some new location as a new Object is being pointed at. So it is not after all a true deep copy in the pure sense, even though in many cases it gives the coder the same benefits as a deep copy.
With arrays of primitive data the Arrays.copyOf(..) method can't copy references as these are not used for primitives. It just copies the source element values into the target elements. Again we have the same effect as a deep copy at the expense of an operation needing much less code than for a deep copy.
So Arrays.copyOf(..) is a 'cheap' deep copy for both primitive and 1-D Object arrays. But any data array more complex and it is found out.
Maybe it should be called a semi-deep copy.
It is a deep copy. It appears shallow in the case of Strings because under the covers, Strings are Singletons. The JVM has a pool of memory for Strings and makes only one copy of each unique string. So you always get a copy of the reference to that string. The example below shows that a deep copy is made for the class Object. When the original array is changed, the copy does not change.
public class ArrayTest {
}
Form Java Doc
So in case of array containing reference, only reference is copied and not the actual object. Which means a shallow copy.
It create Shallow copy because but since java uses parameter by value the copies of all the variable is available in cloned object however for reference type variable copy of address is created and points to same object which is referred by original array so when copied object is modified original object in array also get updated. see the code below.