为了减少可变性,我们应该使用
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) );
}
答案 0 :(得分:39)
Using jmh,我得到了类似的结果,但clone
似乎略微好一些。
我对性能进行了快速测试:clone
,System.arrayCopy
和Arrays.copyOf
具有非常相似的性能(jdk 1.7.06,服务器vm)。
有关详情(以毫秒为单位),请在JIT之后:
克隆:68
arrayCopy:68
Arrays.copyOf:68
测试代码:
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];
}
答案 1 :(得分:4)
我写了一个简单的程序来检查差异。
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()稍快一点。
<强>更新强>
我改变了程序以创建大型数组[100个字符串]而不是小数组。
String[] str = new String[100];
for(int i= 0; i<str.length;i++)
{
str[i]= Integer.toString(i);
}
在copy of
方法之前移动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
答案 2 :(得分:4)
还请考虑使用“clone()”的安全性。一类众所周知的攻击使用使用恶意代码覆盖对象“clone()”方法的类。例如,CVE-2012-0507(Mac OS上的“闪回”攻击)基本上由replacing a ".clone()" call通过“.copyOf”调用来解决。
关于“clone()”过时的补充讨论可以在StackOverflow上找到:object cloning with out implementing cloneable interface
答案 3 :(得分:1)
就可变性而言,它们将提供完全相同的 - 浅层数据。