2017-04-05 112 views
1

我从System.arraycopy的某处读取了基本数据类型和对象引用的浅拷贝。带有基元和对象引用的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

+0

“深副本元”。你怎么能为原语做一个深层次的拷贝呢?根据定义,它们并没有更深层的意思。 – RealSkeptic

回答

2

你有一个误解。

一旦你这样做

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

obj1[1]更换参考。现在这两个数组包含对不同对象的不同引用。

如果你想看到什么被复制是实际的参考,你应该尝试,而不是:

obj1[1].setLength(3); 

现在无论obj1[1]obj2[1]应包含字符串hel,因为你没有更换参考而是更改了内容

+0

现在我明白了。明确解释.. –

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]不再指与obj2[1]相同的StringBuffer实例。这就是为什么Arrays.toString(obj1)Arrays.toString(obj2)的输出不同。

如果代替

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

你会写

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

两个print语句将输出[3, world],因为这两个阵列将仍然指向同一个StringBuffer实例。

0

不,这是浅拷贝的参考。

首先你创建一个new StringBuffer("hello")的引用,然后你做一个浅表副本。所以你有1 StringBuffer,但2引用它。

最后,您完全用new StringBuffer("world")替换其他参考。

+0

如果这样'obj1 == obj2'应该给予真正的权利?但它给出了'false' –

+0

不,它们不是对** **数组的引用,所以当然返回false。 – Kayaman

0

我了解,System.arraycopy做深拷贝的对象 引用如果是这样,如何OBJ1 [0] == obj2的[0]给出真正

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

此外,另一点是System.arrayCopy只做一个浅拷贝(简单地将参考/值从一个数组复制到另一个),您可以参考here

+0

'obj1 [0] == obj2 [0]比较整数值 - 实际上这是错误的。 'obj1 [0]'和'obj2 [0]'指向与arraycopy语句相同的'Integer'对象,这就是为什么'obj1 [0] == obj2 [0]'。如果在arraycopy语句之后添加'obj2 [0] = new Integer(3);'obj1 [0] == obj2 [0]'将不再成立,即使两者仍然具有相同的值3)。 – Eran

+0

谢谢艾兰,我改正了 – developer