.clone()或Arrays.copyOf()?

为了减less可变性,我们应该使用

public void setValues(String[] newVals) { this.vals = ( newVals == null ? null : newVals.clone() ); } 

要么

 public void setValues(String[] newVals) { this.vals = ( newVals == null ? null : Arrays.copyOf(newVals, newVals.length) ); } 

使用jmh更新

使用jmh ,我得到了类似的结果,除了clone似乎稍微好一些。

原帖

我跑了一个快速testing的性能: cloneSystem.arrayCopyArrays.copyOf有非常相似的性能(jdk 1.7.06,服务器虚拟机)。

有关详细信息(以毫秒为单位),在JIT之后:

克隆:68
arrayCopy:68
Arrays.copyOf:68

testing代码:

 public static void main(String[] args) throws InterruptedException, IOException { int sum = 0; int[] warmup = new int[1]; warmup[0] = 1; for (int i = 0; i < 15000; i++) { // triggers JIT sum += copyClone(warmup); sum += copyArrayCopy(warmup); sum += copyCopyOf(warmup); } int count = 10_000_000; int[] array = new int[count]; for (int i = 0; i < count; i++) { array[i] = i; } // additional warmup for main for (int i = 0; i < 10; i++) { sum += copyArrayCopy(array); } System.gc(); // copyClone long start = System.nanoTime(); for (int i = 0; i < 10; i++) { sum += copyClone(array); } long end = System.nanoTime(); System.out.println("clone: " + (end - start) / 1000000); System.gc(); // copyArrayCopy start = System.nanoTime(); for (int i = 0; i < 10; i++) { sum += copyArrayCopy(array); } end = System.nanoTime(); System.out.println("arrayCopy: " + (end - start) / 1000000); System.gc(); // copyCopyOf start = System.nanoTime(); for (int i = 0; i < 10; i++) { sum += copyCopyOf(array); } end = System.nanoTime(); System.out.println("Arrays.copyOf: " + (end - start) / 1000000); // sum System.out.println(sum); } private static int copyClone(int[] array) { int[] copy = array.clone(); return copy[copy.length - 1]; } private static int copyArrayCopy(int[] array) { int[] copy = new int[array.length]; System.arraycopy(array, 0, copy, 0, array.length); return copy[copy.length - 1]; } private static int copyCopyOf(int[] array) { int[] copy = Arrays.copyOf(array, array.length); return copy[copy.length - 1]; } 

我写了一个简单的程序来检查差异。

 public static void main(String[] args) throws IOException, InterruptedException, PrinterException { //Verify array remains immutable. String[] str = {"a","b","c"}; String[] strings = str.clone(); //change returned array strings[2]= "d"; System.out.println(Arrays.toString(str)); System.out.println(Arrays.toString(strings)); String[] stringsCopy = Arrays.copyOf(str, str.length); stringsCopy[2]= "d"; System.out.println(Arrays.toString(str)); System.out.println(Arrays.toString(stringsCopy)); //peformance long before = System.currentTimeMillis(); for(int i=0;i<Integer.MAX_VALUE;i++) { str.clone(); } System.out.println("Time Required for Clone: "+ (System.currentTimeMillis()-before)); //peformance long beforeCopy = System.currentTimeMillis(); for(int i=0;i<Integer.MAX_VALUE;i++) { Arrays.copyOf(str, str.length); } System.out.println("Time Required for Copy of: "+ (System.currentTimeMillis()-beforeCopy)); } 

并输出

 [a, b, c] [a, b, d] [a, b, c] [a, b, d] Time Required for Clone: 26288 Time Required for Copy of: 25413 

所以如果你在两种情况下看到String[]是不可变的,而且性能几乎相同,Arrays.copyOf()在我的机器上稍微快一点。

更新

我改变了程序来创build大数组[100个string]而不是小数组。

  String[] str = new String[100]; for(int i= 0; i<str.length;i++) { str[i]= Integer.toString(i); } 

clone方法之前移动方法的clone 。 以下结果。

  Time Required for Copy of: 415095 Time Required for Clone: 428501 

这又是更多的相同。 Please do not ask me to run the test again as it takes a while 🙁

更新2

对于string数组1000000和迭代次数10000

 Time Required for Copy of: 32825 Time Required for Clone: 30138 

copy of比克隆需要更多的时间

请考虑使用“clone()”的安全性。 一类众所周知的攻击使用类来覆盖具有恶意代码的对象“clone()”方法。 例如,CVE-2012-0507(Mac OS上的“闪回”攻击)是通过用“.copyOf”调用基本上replace“.clone()”调用来解决的。

关于“clone()”过时性的其他讨论可以在StackOverflow中find: 对象克隆与实现可复制的接口

就可变性而言,它们将提供完全相同的数据的浅层副本。