Java 深复制和浅复制

  浅复制是指复制对象时仅仅复制对象本身(包括对象中的基本变量),而不复制对象包含的引用指向的对象。深复制不仅复制对象本身,而且复制对象包含的引用指向的对象。

  复制对象时需要调用Object类的clone方法:

1 protected native Object clone() throws CloneNotSupportedException;

  步骤:

  1 被复制的类需要实现Clonenable接口(不实现的话在调用clone方法时会抛出CloneNotSupportedException异常) 。而该接口为标记接口(不含任何抽象方法)。

  2 重写clone()方法,访问修饰符设为public,通过调用super.clone()方法得到需要的复制对象。

  

  浅复制

 1 class Address  {
 2     private String add;
 3 
 4     public String getAdd() {
 5         return add;
 6     }
 7 
 8     public void setAdd(String add) {
 9         this.add = add;
10     }
11     
12 }
13 
14 class Student implements Cloneable{
15     private int number;
16 
17     private Address addr;
18     
19     public Address getAddr() {
20         return addr;
21     }
22 
23     public void setAddr(Address addr) {
24         this.addr = addr;
25     }
26 
27     public int getNumber() {
28         return number;
29     }
30 
31     public void setNumber(int number) {
32         this.number = number;
33     }
34     
35     @Override
36     public Object clone() {
37         Student stu = null;
38         try{
39             stu = (Student)super.clone();
40         }catch(CloneNotSupportedException e) {
41             e.printStackTrace();
42         }
43         return stu;
44     }
45 }
46 public class Test {
47     
48     public static void main(String args[]) {
49         
50         Address addr = new Address();
51         addr.setAdd("杭州市");
52         Student stu1 = new Student();
53         stu1.setNumber(123);
54         stu1.setAddr(addr);
55         
56         Student stu2 = (Student)stu1.clone();
57         
58         System.out.println("学生1:" + stu1.getNumber() + ",地址:" + stu1.getAddr().getAdd());
59         System.out.println("学生2:" + stu2.getNumber() + ",地址:" + stu2.getAddr().getAdd());
60 
61         addr.setAdd("西湖区");
62         
63         System.out.println("学生1:" + stu1.getNumber() + ",地址:" + stu1.getAddr().getAdd());
64         System.out.println("学生2:" + stu2.getNumber() + ",地址:" + stu2.getAddr().getAdd());
65     }
66 }

  结果如下:

1 学生1:123,地址:杭州市  
2 学生2:123,地址:杭州市
3 学生1:123,地址:杭州市  
4 学生2:123,地址:杭州市  
5 学生1:123,地址:西湖区  
6 学生2:123,地址:西湖区

  两个学生的地址都改变了。原因是浅复制只是复制了addr变量的引用,并没有真正地开辟另一块空间来存储地址对象。

  

  深复制

 1 class Address implements Cloneable {
 2     private String add;
 3 
 4     public String getAdd() {
 5         return add;
 6     }
 7 
 8     public void setAdd(String add) {
 9         this.add = add;
10     }
11     
12     @Override
13     public Object clone() {
14         Address addr = null;
15         try{
16             addr = (Address)super.clone();
17         }catch(CloneNotSupportedException e) {
18             e.printStackTrace();
19         }
20         return addr;
21     }
22 }
23 
24 class Student implements Cloneable{
25     private int number;
26 
27     private Address addr;
28     
29     public Address getAddr() {
30         return addr;
31     }
32 
33     public void setAddr(Address addr) {
34         this.addr = addr;
35     }
36 
37     public int getNumber() {
38         return number;
39     }
40 
41     public void setNumber(int number) {
42         this.number = number;
43     }
44     
45     @Override
46     public Object clone() {
47         Student stu = null;
48         try{
49             stu = (Student)super.clone();    //浅复制
50         }catch(CloneNotSupportedException e) {
51             e.printStackTrace();
52         }
53         stu.addr = (Address)addr.clone();    //深度复制
54         return stu;
55     }
56 }
57 public class Test {
58     
59     public static void main(String args[]) {
60         
61         Address addr = new Address();
62         addr.setAdd("杭州市");
63         Student stu1 = new Student();
64         stu1.setNumber(123);
65         stu1.setAddr(addr);
66         
67         Student stu2 = (Student)stu1.clone();
68         
69         System.out.println("学生1:" + stu1.getNumber() + ",地址:" + stu1.getAddr().getAdd());
70         System.out.println("学生2:" + stu2.getNumber() + ",地址:" + stu2.getAddr().getAdd());
71         
72         addr.setAdd("西湖区");
73         
74         System.out.println("学生1:" + stu1.getNumber() + ",地址:" + stu1.getAddr().getAdd());
75         System.out.println("学生2:" + stu2.getNumber() + ",地址:" + stu2.getAddr().getAdd());
76     }
77 }

  结果如下:

1 学生1:123,地址:杭州市
2 学生2:123,地址:杭州市
3 学生1:123,地址:西湖区
4 学生2:123,地址:杭州市

  

  参考资料

  java.util.ArrayList.clone是不是彻底的克隆

  Java如何复制对象

原文地址:https://www.cnblogs.com/WJQ2017/p/7601784.html