我在某处读到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 :(得分: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。