Using System.arraycopy
or Arrays.copyOf
instead of clone()
makes your code more explicit and therefore easier to understand. It says "I'm copying an array" as opposed to "I'm (magically) copying some kind of object".
Explicit is better than implicit.
- The Zen of Python
But the main argument in favor of the Arrays.copyOf
methods (and against clone()
) is type-safety, the lack of which is probably the biggest gotcha of clone()
that could lead to subtle bugs if you're not careful that the object you're cloning has the exact array component type that you want.
Let's look at the JDK-6260652 bug for example. The culprit was clone()
being used in Arrays.ArrayList
to implement Collection.toArray()
(which is declared to return Object[]
). This particular ArrayList
is a private class in java.util.Arrays
instantiated by Arrays.asList(T... a)
using a
as its backing array without caring about the actual type of a
, which might have been a String[]
or Integer[]
(or whatever else that's not actually Object[]
). The problem with its toArray()
method returning a.clone()
here is that a programmer might end up using Arrays.ArrayList.toArray()
at some point to do something like this:
List<String> lst = Arrays.asList("a", "b", "c");
// ... many lines of code later ...
Object[] arr = lst.toArray();
// ... at this point don't care about the original type of elements in lst ...
arr[0] = 123; // ArrayStoreException - WTF?!
// arr is an Object[] so should be able to store Integer values!
This kind of bug can go unnoticed for years because the usage pattern illustrated above is not common. Just consider that the Collections framework has been around since JDK 1.2 (1998) but this particular issue wasn't reported until 2005 (and 10 years later someone discovered a similar issue in a different part of the JDK). The patch for JDK-6260652 (released in Java 9) simply replaces a.clone()
with Arrays.copyOf(a, a.length, Object[].class)
.
To summarize, my arguments in favor of using the array copy methods instead of clone()
are:
System.arraycopy
:
- more explicit
Arrays.copyOf
:
- more explicit
- and provides type-safety
System.arraycopy
copies each element fromorig
todest
, which then is a deep copy, not shallow. – Keladest[0]
refer to the same object asorig[0]
. So iforig[0]
is an array,dest[0]
will contain the exact same array instance; it will not clone the sub-array. This is not a deep copy. Is this not correct? – Kareeint
primitives. Thendest[0]
gets the value thatorig[0]
had at the time of copying. Iforig[0]
's value changes after that, it doesn't affectdest[0]
's value any more. If the value is an object reference (as would be in anObject[]
array (whose elements could be e.g.int[]
arrays), then the object may of course mutate. – Kelaarraycopy
is no "deeper" thanclone
, whatever your meaning of deep/shallow might be. – Karee