“浅”或“深” - 这是我看到没有人精确定义的问题 - 方法 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(..)` 方法确实给了他们这个。
与原始类型数组一样,字符串对象数组的行为也与上面的示例一样,输出如下:
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”连接时。
它也适用于 Object 数组,因为当重新分配后者时,目标不再与源绑定。
但是在复制之后查看两个数组的第一个元素的输出,然后在更改 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(..) 是原始数组和一维对象数组的“廉价”深拷贝。
但是任何更复杂的数据数组都被找出来了。
或许应该叫半深拷贝。