'浅层复制'或'深层复制' - 这是一个我看到没有人定义清楚的问题 - 方法Arrays.copyOf(..)
在实践中确实会产生源数组的副本,该副本不受源数组更改的影响。
以int数组为例,看下面这个简单的例子:
import java.util.Arrays;
public class DeepCopyTest
{
public static void main(String[] args)
{
int[] source = { 1, 2, 3, 4, 5, 6};
int[] target = new int[source.length];
target = Arrays.copyOf(source, 6);
System.out.println("Source1 : " + Arrays.toString(source));
System.out.println("Target1 : " + Arrays.toString(target));
for(int i = 0; i < source.length; i++)
{
source[i] = source[i] +1;
}
System.out.println("Source2 : " + Arrays.toString(source));
System.out.println("Target2 : " + Arrays.toString(target));
}
}
Source1 : [1, 2, 3, 4, 5, 6]
Target1 : [1, 2, 3, 4, 5, 6]
Source2 : [2, 3, 4, 5, 6, 7]
Target2 : [1, 2, 3, 4, 5, 6]
实际上,当人们寻求一个数组的“深拷贝”时,他们只是希望得到一个与原始数组更改无关的东西。
而这个 Arrays.copyOf(..) 方法确实可以给他们这个。
除了基本数据类型数组外,String 对象数组也像上面的例子一样运行,输出类似于:
Source1 : [a, b, c, d, e, f]
Target1 : [a, b, c, d, e, f]
Source2 : [a1, b1, c1, d1, e1, f1]
Target2 : [a, b, c, d, e, f]
当初始源数组条目被“1”连接时。
对于对象数组,它也“可以工作”,因为当后者被重新分配时,目标不再与源相关联。但是,在复制并修改source [0]之后,查看两个数组的第一个元素的输出会揭示全部真相:
Source1 : java.lang.Object@1db9742
Target1 : java.lang.Object@1db9742
Source2 : java.lang.Object@106d69c
Target2 : java.lang.Object@1db9742
在复制原始源数组后,目标元素只是指向其源对应项当前持有的任何值。对于目标[0]来说,它指向内存地址1db9742中的内容,这也是保存源[0]的相同内存地址......
当重新分配源[0]之后,我们会看到源和目标之间出现解绑的原因是赋值语句......
source[0] = new Object();
简单地说,使用 Arrays.copyOf(..) 方法可以将源数组中的内存引用更改为指向新对象的位置,从而实现复制。虽然在许多情况下它可以给程序员带来与深拷贝相同的好处,但它并不是真正意义上的深拷贝。
对于基本数据类型的数组,Arrays.copyOf(..) 方法无法复制引用,因为这些引用不适用于基本数据类型。它只会将源元素值复制到目标元素中。同样,我们可以通过这种方法获得类似于深拷贝的效果,但所需代码远少于深拷贝。
因此,Arrays.copyOf(..) 方法是一种廉价的深拷贝方式,适用于基本数据类型和一维对象数组。但对于任何更复杂的数据数组,它都会暴露问题。
也许它应该被称为半深拷贝。
= "Bar"
修改了。 - ToolmakerSteve