Is there any reason to prefer System.arraycopy() over clone()?
Solution 1
No. If you're really microbenchmarking, then maybe, depending on what JVM you're running. But in actuality, no.
Solution 2
I happened to look at this question when I was pondering on the same doubt. I feel that the arraycopy()
is a method to be used when the array is predefined (i.e. memory is already allocated). Thus, the overhead associated with memory allocation is not repeated.
For example, imagine a case when you have defined a large array which is updated periodically. Then using clone()
will recreate a array of required size every time the array is copied. However, arraycopy()
uses the pre-allocated memory space.
Thus arraycopy()
is more efficient in certain scenarios compared to clone()
. On the other hand clone()
results in a compact code.
Solution 3
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
Solution 4
Just guessing here, but there might be a good reason to use System.arraycopy
because different JVM's could conceivably implement them in a way that takes advantage of native abilities of the underlying system for a performance boost.
For example, a JVM implementation could use a native library call like memcpy
which could potentially take advantage of some memory controller tricks to perform the action in some incredibly fast and clever way. However, the Object.clone
implementation might not be a good candidate for such optimization due to its virtual nature.
Neil Traft
A software engineer with >10 years of professional experience in Python, Java, and C++. I have experience in robotics, machine learning, cloud computing, and statistical data analysis. In a prior life I had some experience in 3D visualization, user interfaces, and Android apps. I hold a master's degree in computer science with a focus on robotics. ntraft.com @ntraft
Updated on October 08, 2022Comments
-
Neil Traft over 1 year
When copying an entire array, I've often seen people write:
int[] dest = new int[orig.length]; System.arraycopy(orig, 0, dest, 0, orig.length);
But it seems to me there is no reason to favor this over:
int[] dest = orig.clone();
They're both shallow copies anyway. Probably these folks just don't realize that
clone
exists. So is there any reason not to useclone
? -
Admin over 12 yearsarrayCopy uses JNI to copy; it is really fast.
-
maerics over 12 yearsWell, the particular JVM implementation they are benchmarking apparently does but I don't think you can say categorically that all JVMs do the same.
-
Neil Traft over 12 yearsI'm a bit confused on this. The JVM implements both arraycopy and clone, right? So why wouldn't the implementations be similar? What do you mean "its virtual nature?"
-
maerics over 12 years@Neil Traft: I'm guessing that the JVM implements
arraycopy
as a native method butObject.clone
is implemented in the Java language itself (as part of the standard class library). By "virtual nature" I mean that the rootObject
class implementation has a "clone" method but subclasses override them with their own implementation, so perhaps this "virtual method dispatch" complicates the ability to do the sort of optimization tricks I imagine. -
Neil Traft over 12 years@maerics: But... when I look at the source code for Object.java from the Sun JDK distribution, it says "protected native Object clone()".
-
maerics over 12 years@Neil Traft: well, looks like my guess was wrong =) I suppose they could do the same fancy optimization tricks in
Object.clone
. Of course, this is all totally implementation dependent. Each JVM might be different from the next. -
WestCoastProjects about 3 yearswhat about performance? I have just read that
clone()
is much faster thatSystem.arraycopy()
but am looking for corroboration