我长期以来一直与Java的容器的复制构造函数混淆,是浅复制还是深副本?以下是我的理解:ints1,ints2,ints3是参考文献,因此它们位于堆栈中。Inst1指向堆中的某个对象,并且该对象包含三个匿名引用,它们位于堆栈中,它们指向具有int值0、1、2的对象。
ints2 = ints1
因此,ints2指向与ints1相同的对象。因此。
ints2.set(1,0+10)
将更改Refenence ints1.get(0)的对象。
ints3 = new ArrayList<>(ints1)
接下来是我的困惑。
如果复制构造函数是浅副本,则尽管ints1和ints3指向不同的对象,但两个对象具有相同的引用!因此,通过操纵ints1中的参考来更改对象的任何动作都会更改ints3,因为它们指向相同的对象。
如果复制构造函数是深拷贝,则INTS1和INTS3将保存不同的引用并指向不同的对象。那么INTS1的变化将不会影响INTS3中的变化。
根据结果,复制构造函数似乎是深副本,而不是浅副本。
希望有人能纠正我,谢谢
import java.util.*;
public class MyClass {
public static void main(String args[]) {
List<Integer> ints1 = new ArrayList<>(Arrays.asList(0,1,2));
System.out.println(ints1);
List<Integer> ints2 = ints1;
ints2.set(0,0+10);
System.out.println(ints1);
List<Integer> ints3 = new ArrayList<>(ints1);
ints3.set(1,1+10);
System.out.println(ints1);
}
}
result
[0, 1, 2]
[10, 1, 2]
[10, 1, 2]
答案是:浅副本。请看一下这篇文章,其中提供了有关该主题的更多详细信息:http://javarevisited.blogspot.co.uk/2014/03/how-to-clone-collection-collection-in-collection-in-java-in-java-deep-copy-vs-nallow。html?m = 1
问题的关键是,当您进行ints3.set(1, 1+10)
时,您实际上正在更改ints3[1]
中存储的参考。ints1[1]
中存储的参考文献不受此影响。
// Format
----------
| Value |
----------
Address
// Actual data
------ ------ ------- ------
| 1 | ...| 2 | ... | 3 | ...... | 42 |
------ ------ ------- ------
10 20 30 80
// ArrayList <Integer> a = new ArrayList <Integer> (Arrays.asList(1, 2, 3));
------ ------ ------ ------
| 100 | ---> | 10 | 20 | 30 |
------ ------ ------ ------
a 100 104 108
// ArrayList <Integer> b = new ArrayList <Integer> (a);
------ ------ ------ ------
| 200 | ---> | 10 | 20 | 30 |
------ ------ ------ ------
b 200 204 208
When you do:
a[1] = 42, it is equivalent to:
------ ------ ------ ------
| 100 | ---> | 10 | 80 | 30 |
------ ------ ------ ------
a 100 104 108
Note that this does not change b in any way.
另外,请查看以下代码。在这里,您可以看到它确实是浅副本,因为当您修改参考指向的值时,它会反映在a
和b
中。
import java.io.*;
import java.util.ArrayList;
import java.util.Arrays;
class Node {
int data;
String name;
Node(int data, String name) {
this.data = data;
this.name = name;
}
public String toString() {
return "{" + Integer.toString(data) + ", " + name + "}";
}
}
class ArrayListTest {
public static void main(String[] args) {
ArrayList <Node> a = new ArrayList <Node>();
Node n[] = new Node[5];
for(int i = 0; i < 5; i++) {
n[i] = new Node(i, Integer.toString(i));
}
a.add(n[0]);
a.add(n[1]);
a.add(n[2]);
System.out.println("Previously: ");
System.out.println("a = " + a.toString());
ArrayList <Node> b = new ArrayList <Node> (a);
System.out.println("b = " + b.toString());
// This does not affect b as b has aready made a copy of
// all the references in a different location.
a.add(n[3]);
n[2].data = 10;
n[2].name = "10";
System.out.println("nCurrent: ");
System.out.println("a = " + a.toString());
System.out.println("b = " + b.toString());
}
}