.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的性能: clone
, System.arrayCopy
和Arrays.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: 对象克隆与实现可复制的接口
就可变性而言,它们将提供完全相同的数据的浅层副本。