是否有理由更喜欢System.arraycopy()而不是clone()?

Nei*_*aft 33 java arrays clone

复制整个数组时,我经常看到人们写道:

int[] dest = new int[orig.length];
System.arraycopy(orig, 0, dest, 0, orig.length);
Run Code Online (Sandbox Code Playgroud)

但在我看来,没有理由支持这一点:

int[] dest = orig.clone();
Run Code Online (Sandbox Code Playgroud)

无论如何,它们都是浅色的.可能这些人只是没有意识到clone存在.那么有什么理由不使用clone

小智 33

  • clone() 使用自己的引用制作第一个数组的不同副本.
  • System.arraycopy()使用JNI(Java Native Interface)来复制一个数组(或部分数组),所以它非常快,你可以在这里确认 一下 ;
  • clone()创建一个新的具有相同特征的老阵列,即,相同的大小,相同的类型,并且阵列相同的内容.请参阅此处了解一些实际操作示例clone;
  • manual copying是,手动复制.没有太多的话要说,该方法相同,只是很多人都认为它是最高性能.
  • arraynew = arrayold 复制数组; 它只是指向 arraynew内存地址,arrayold或者换句话说,你只是指定一个旧数组的引用.

  • @Code Monkey:从文章本身开始:"使用clone()来复制数组的代码较少,而且正如我们所看到的,性能差异只对微小数组有意义.我认为将来我宁愿使用clone()而不是System .arrayCopy()". (4认同)
  • 你没有回答我的问题.另外,我希望`clone`和`arraycopy`一样快.它不是原生的吗? (2认同)
  • @Neil:克隆速度较慢.见第一个链接. (2认同)

Nei*_*aft 8

不.如果你真的是微基准测试,那么可能,取决于你正在运行的JVM.但实际上,没有.


typ*_*cer 6

使用System.arraycopyorArrays.copyOf代替clone()会使您的代码更明确,因此更容易理解。它说“我正在复制一个数组”,而不是“我正在(神奇地)复制某种对象”

显式的比隐式的好。- Python 之禅

但支持这些Arrays.copyOf方法(和反对clone())的主要论据是类型安全,缺乏类型安全可能是最大的问题,clone()如果您不小心克隆的对象具有精确的类型,则可能会导致微妙的错误。您想要的数组组件类型。

让我们以JDK-6260652错误为例。罪魁祸首被clone()用来Arrays.ArrayList实现Collection.toArray()(声明为 return Object[])。这个特殊的类是通过用作其后备数组来实例化的ArrayList私有类,而不关心 的实际类型,它可能是or (或实际上不是的任何其他类型)。其方法在此处返回的问题是,程序员最终可能会在某个时候使用做这样的事情:java.util.ArraysArrays.asList(T... a)aaString[]Integer[]Object[]toArray()a.clone()Arrays.ArrayList.toArray()

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!
Run Code Online (Sandbox Code Playgroud)

这种错误可能会被忽视很多年,因为上面说明的使用模式并不常见。只要考虑一下集合框架自 JDK 1.2(1998 年)以来就已经存在,但这个特定问题直到 2005 年才被报告(10 年后有人在 JDK 的不同部分发现了类似的问题)。JDK-6260652(在 Java 9 中发布)的补丁只是a.clone()Arrays.copyOf(a, a.length, Object[].class).


总而言之,我赞成使用数组复制方法的论点是clone()

  • System.arraycopy:
    1. 更明确
  • Arrays.copyOf:
    1. 更明确
    2. 并提供类型安全


Sou*_*hat 5

当我在思考同样的疑问时,我偶然看到了这个问题.我觉得这arraycopy()是一个在预定义数组时使用的方法(即已经分配了内存).因此,不重复与存储器分配相关的开销.

例如,假设您定义了一个定期更新的大型数组.然后使用clone()将在每次复制数组时重新创建所需大小的数组.但是,arraycopy()使用预先分配的内存空间.

因此,arraycopy()在某些情况下,与之相比,效率更高clone().另一方面,clone()结果是紧凑的代码.