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
,因为您没有替换引用而是 更改了内容 .
我在某处读到 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
,因为您没有替换引用而是 更改了内容 .