System.arraycopy() 具有原始和对象引用的浅拷贝或深拷贝

System.arraycopy() shallow copy or deepcopy with primitive and object references

我在某处读到 System.arraycopy 确实为原始数据类型创建了一个新副本,为对象引用创建了一个浅表副本。

所以,我用下面的代码开始了实验

//trying with primitive values
int a[] ={1,2,3};
int b[] = new int[a.length];
System.arraycopy(a,0,b,0,a.length);
b[0] = 9;
System.out.println(Arrays.toString(a));
System.out.println(Arrays.toString(b));
//now trying with object references
Object[] obj1 = {new Integer(3),new StringBuffer("hello")};
Object[] obj2 = new Object[obj1.length];
System.arraycopy(obj1,0,obj2,0,obj1.length);
obj1[1] = new StringBuffer("world");
System.out.println(Arrays.toString(obj1));
System.out.println(Arrays.toString(obj2));

输出为

[1, 2, 3]
[9, 2, 3]
[3, world]
[3, hello]

但我期望的是

[1, 2, 3]
[9, 2, 3]
[3, world]
[3, world]

从上面的代码,我了解到System.arraycopy对对象引用做深拷贝 如果是这样,obj1[0] == obj2[0] 如何给出 true

System.arraycopy 进行浅拷贝,这意味着它在应用于非原始数组时复制 Object 引用。

因此在 System.arraycopy(obj1,0,obj2,0,obj1.length);obj1[0]==obj2[0]obj1[1]==obj2[1] 之后,因为两个数组都包含对相同 Object 的引用。

将新值分配给 obj1[1] 后,obj1[1] 不再引用与 obj2[1] 相同的 StringBuffer 实例。这就是 Arrays.toString(obj1)Arrays.toString(obj2) 的输出不同的原因。

如果不是

obj1[1] = new StringBuffer("world");

你会写

obj1[1].setLength(0);
obj1[1].append("world");

两个打印语句都会输出 [3, world],因为两个数组仍将引用同一个 StringBuffer 实例。

不,它是供参考的浅拷贝。

首先创建对 new StringBuffer("hello") 的引用,然后对其进行浅表复制。所以你有 1 个 StringBuffer,但有 2 个引用。

最后你用完整的 new StringBuffer("world") 替换了另一个参考。

I understood that System.arraycopy does deep copy for object references If so, how obj1[0] == obj2[0] gives true

不,你错了,它不执行深拷贝。因为 obj1[0] == obj2[0] 在两个数组中引用相同的整数对象(即存储在索引“0”的数组中的引用),所以你得到的答案是 true。此外,您可以比较 obj1[1] == obj2[1] 和 returns false,因为两个 StringBuffer 引用是不同的。

还有一点就是System.arrayCopy只做浅拷贝(只是把references/values从一个数组复制到另一个数组),你可以参考here

你误会了。

一旦你这样做了

obj1[1] = new StringBuffer("world");

替换了 obj1[1] 中的引用 。现在这两个数组包含对不同对象的不同引用。

如果您想查看复制的是实际引用,您应该试试:

obj1[1].setLength(3);

现在 obj1[1]obj2[1] 都应该包含字符串 hel,因为您没有替换引用而是 更改了内容 .