“浅”或“深” - 这是我看到没有人精确定义的问题 - 该方法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];
// Copy target from source via Arrays.copyOf(..) method :
target = Arrays.copyOf(source, 6);
// Check for equality :
System.out.println("Source1 : " + Arrays.toString(source));
System.out.println("Target1 : " + Arrays.toString(target));
// Increment all entries in source array :
for(int i = 0; i < source.length; i++)
{
source[i] = source[i] +1;
}
// See if target is affected :
System.out.println("Source2 : " + Arrays.toString(source));
System.out.println("Target2 : " + Arrays.toString(target));
}
}
// OUTPUT
// ------
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
在复制原始源数组后,目标元素只是简单地指向了它们的源对应项中当前保存的任何值。对于 target[0] 它是内存地址 1db9742 的内容——这也是保存 source[0] 的相同内存地址。. . .
在重新分配 source[0] 后,我们在源和目标之间解除绑定的原因是因为赋值语句
source[0] = new Object();
只是导致在 source[0] 中保存的内存引用在指向新对象时更改为某个新位置。所以它毕竟不是纯粹意义上的真正的深拷贝,尽管在许多情况下它给编码者带来了与深拷贝相同的好处。
对于原始数据数组,Arrays.copyOf(..) 方法不能复制引用,因为这些引用不用于原始数据。它只是将源元素值复制到目标元素中。同样,我们与深拷贝具有相同的效果,但代价是操作需要的代码比深拷贝少得多。
因此 Arrays.copyOf(..) 是原始数组和一维对象数组的“廉价”深拷贝。但是任何更复杂的数据数组都会被发现。
也许它应该被称为半深拷贝。