System.arraycopy()浅复制或带有基元和对象引用的深度复制

时间:2017-04-05 06:27:25

标签: java arrays deep-copy shallow-copy

我在某处读到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

的方式

4 个答案:

答案 0 :(得分:2)

你有一种误解。

一旦你做了

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

您已将替换为obj1[1]中的参考。现在,这两个数组包含对不同对象的不同引用。

如果你想看到复制的是实际的引用,你应该尝试:

obj1[1].setLength(3);

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

答案 1 :(得分:1)

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

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

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

如果不是

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

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

两个print语句都会输出[3, world],因为两个数组仍会引用相同的StringBuffer实例。

答案 2 :(得分:0)

不,它是参考文献的浅层副本。

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

最后,用完全new StringBuffer("world")替换另一个引用。

答案 3 :(得分:0)

  

我知道System.arraycopy会为对象执行深层复制   如果是这样,obj1 [0] == obj2 [0]如何给出真实的

不,你错了,它没有执行深层复制。因为 obj1[0] == obj2[0]引用两个数组内的相同整数对象(即存储在数组中的索引' 0'),所以你得到的答案是true。此外,您可以比较返回obj1[1] == obj2[1]的{​​{1}},因为false引用都不同。

另外,另一点是StringBuffer只做一个浅拷贝(简单地将引用/值从一个数组复制到另一个数组),你可以参考here