Java浅拷贝与深拷贝(思维导图)

图1 拷贝思维导图(点击查看图片)

1,拷贝

  有两个相同属性的对象A和B,A拥有初始化值,将其值拷贝到B中,使得B拥有与A“相同”数据的属性!注意这里的相同我有加双引号!

  相同可能表示这么几个意思:①数值相同【指向不同的内存空间】;②地址相同【指向相同的内存空间】;

  下面是直接使用"="进行复制的操作

 1 package com.cnblogs.mufasa.Demo1;
 2 
 3 import java.util.Date;
 4 
 5 class Person{//
 6     private int age=0;
 7     private Birth birth=new Birth();
 8     private String name="";
 9 
10     public Person(int age, Birth birth, String name) {
11         this.age = age;
12         this.birth = birth;
13         this.name = name;
14     }
15 
16     public int getAge() {
17         return age;
18     }
19 
20     public void setAge(int age) {
21         this.age = age;
22     }
23 
24     public Birth getBirth() {
25         return birth;
26     }
27 
28     public void setBirth(Birth birth) {
29         this.birth = birth;
30     }
31 
32     public String getName() {
33         return name;
34     }
35 
36     public void setName(String name) {
37         this.name = name;
38     }
39     public String toString(){
40         return "姓名:"+name+",年龄:"+age+",出生日期:"+birth.toString();
41     }
42 }
43 
44 class Birth{//生日
45     private String date="";
46     public Birth(){}
47     public Birth(String date){
48         this.date=date;
49     }
50 
51     public String getDate() {
52         return date;
53     }
54 
55     public void setDate(String date) {
56         this.date = date;
57     }
58 
59     @Override
60     public String toString() {
61         return this.date;
62     }
63 }
64 
65 public class Demo1 {//浅拷贝
66     public static void main(String[] args) {
67         Person p1=new Person(18,new Birth("19950729"),"万雨");
68         Person p2=p1;
69         System.out.println(p1.toString());
70         System.out.println(p2.toString());
71 
72         p1.setAge(17);
73         p1.setBirth(new Birth("2018"));
74         p1.setName("Mufasa");
75 
76         System.out.println(p1.toString());
77         System.out.println(p2.toString());
78 
79     }
80 }
View Code
姓名:万雨,年龄:18,出生日期:19950729
姓名:万雨,年龄:18,出生日期:19950729
姓名:Mufasa,年龄:17,出生日期:2018
姓名:Mufasa,年龄:17,出生日期:2018

  其实就相当于对原始对象进行操作

 

2,浅拷贝

  Perosn类型对象有两个属性Age、name,将p1浅复制给p2

  基本类型直接进行数值复制,引用类型进行地址拷贝(String类型比较特殊,属于引用类型,但是它存在一个常量池需要进行特殊对待)

 图2 浅拷贝

使用构造方法进行浅拷贝:

 1 package com.cnblogs.mufasa.Demo;
 2 
 3 import java.util.Date;
 4 
 5 class Person{//
 6     private Age age;
 7     private String name;
 8     private int birth;
 9     public Person(Age age, String name,int birth) {
10         this.age = age;
11         this.name = name;
12         this.birth = birth;
13     }
14 
15     public Person(Person p1){
16         this.age=p1.age;
17         this.name=p1.name;
18         this.birth=p1.birth;
19     }
20 
21     public int getAge() {
22         return this.age.getAge();
23     }
24 
25     public void setAge(int age) {
26         this.age.setAge(age); ;
27     }
28 
29     public void setAge(Age age) {
30         this.age = age;
31     }
32 
33     public int getBirth() {
34         return birth;
35     }
36 
37     public void setBirth(int birth) {
38         this.birth = birth;
39     }
40 
41     public String getName() {
42         return this.name;
43     }
44 
45     public void setName(String name) {
46         this.name = name;
47     }
48     public String toString(){
49         return "姓名:"+this.name+",年龄:"+this.age+",出生日期:"+this.birth;
50     }
51 }
52 
53 class Age{
54     private int age;
55     public Age(){}
56     public Age(int age){
57         this.age=age;
58     }
59 
60     public int getAge() {
61         return age;
62     }
63 
64     public void setAge(int age) {
65         this.age = age;
66     }
67     public String toString(){
68         return this.age+"";
69     }
70 }
71 
72 
73 
74 
75 public class Demo {//浅拷贝-构造方法实现
76     public static void main(String[] args) {
77         Person p1=new Person(new Age(18),"万雨",1995);
78         Person p2=new Person(p1);
79         System.out.println(p1.toString());
80         System.out.println(p2.toString());
81 
82         p1.setAge(17);
83         p1.setBirth(2019);
84         p1.setName("Mufasa");
85 
86         System.out.println(p1.toString());
87         System.out.println(p2.toString());
88 
89     }
90 }
View Code

 

使用继承Cloneable接口调用clone方法进行浅拷贝

  1 package com.cnblogs.mufasa.Demo2;
  2 
  3 import java.util.Date;
  4 
  5 class Person implements Cloneable{//
  6     private Age age;
  7     private String name;
  8     private int birth;
  9     public Person(Age age, String name,int birth) {
 10         this.age = age;
 11         this.name = name;
 12         this.birth = birth;
 13     }
 14 
 15     public Person clone(){
 16         Person obj=null;
 17         try {
 18             obj=(Person) super.clone();
 19         }catch (CloneNotSupportedException e){
 20             e.printStackTrace();
 21         }
 22 //        obj.age=(Age) this.getAge().clone();
 23         return obj;
 24     }
 25 
 26     public Age getAge() {
 27         return this.age;
 28     }
 29 
 30     public void setAge(int age) {
 31         this.age.setAge(age); ;
 32     }
 33 
 34     public void setAge(Age age) {
 35         this.age = age;
 36     }
 37 
 38     public int getBirth() {
 39         return birth;
 40     }
 41 
 42     public void setBirth(int birth) {
 43         this.birth = birth;
 44     }
 45 
 46     public String getName() {
 47         return this.name;
 48     }
 49 
 50     public void setName(String name) {
 51         this.name = name;
 52     }
 53     public String toString(){
 54         return "姓名:"+this.name+",年龄:"+this.age+",出生日期:"+this.birth;
 55     }
 56 }
 57 
 58 class Age implements Cloneable{
 59     private int age;
 60     public Age(){}
 61     public Age(int age){
 62         this.age=age;
 63     }
 64 //    public Age clone(){
 65 //        Age obj=null;
 66 //        try {
 67 //            obj=(Age) super.clone();
 68 //        }catch (CloneNotSupportedException e){
 69 //            e.printStackTrace();
 70 //        }
 71 //        return obj;
 72 //    }
 73 
 74     public int getAge() {
 75         return age;
 76     }
 77 
 78     public void setAge(int age) {
 79         this.age = age;
 80     }
 81     public String toString(){
 82         return this.age+"";
 83     }
 84 }
 85 
 86 
 87 
 88 
 89 public class Demo2 {//浅拷贝-继承Cloneable接口实现
 90     public static void main(String[] args) {
 91         Person p1=new Person(new Age(18),"万雨",1995);
 92         Person p2=(Person)p1.clone();
 93         System.out.println(p1.toString());
 94         System.out.println(p2.toString());
 95 
 96         p1.setAge(17);
 97         p1.setBirth(2019);
 98         p1.setName("Mufasa");
 99 
100         System.out.println(p1.toString());
101         System.out.println(p2.toString());
102 
103     }
104 }
View Code
姓名:万雨,年龄:18,出生日期:1995
姓名:万雨,年龄:18,出生日期:1995
姓名:Mufasa,年龄:17,出生日期:2019
姓名:万雨,年龄:17,出生日期:1995

 

3,深拷贝

   引用类型数据也进行新内存开辟与幅值,

图3 深拷贝

使用继承Cloneable接口调用clone方法进行深拷贝【每个引用对象都需要使用clone方法进行拷贝】

  1 package com.cnblogs.mufasa.Demo2;
  2 
  3 import java.util.Date;
  4 
  5 class Person implements Cloneable{//
  6     private Age age;
  7     private String name;
  8     private int birth;
  9     public Person(Age age, String name,int birth) {
 10         this.age = age;
 11         this.name = name;
 12         this.birth = birth;
 13     }
 14 
 15     public Person clone(){
 16         Person obj=null;
 17         try {
 18             obj=(Person) super.clone();
 19         }catch (CloneNotSupportedException e){
 20             e.printStackTrace();
 21         }
 22         obj.age=(Age) this.getAge().clone();
 23         return obj;
 24     }
 25 
 26     public Age getAge() {
 27         return this.age;
 28     }
 29 
 30     public void setAge(int age) {
 31         this.age.setAge(age); ;
 32     }
 33 
 34     public void setAge(Age age) {
 35         this.age = age;
 36     }
 37 
 38     public int getBirth() {
 39         return birth;
 40     }
 41 
 42     public void setBirth(int birth) {
 43         this.birth = birth;
 44     }
 45 
 46     public String getName() {
 47         return this.name;
 48     }
 49 
 50     public void setName(String name) {
 51         this.name = name;
 52     }
 53     public String toString(){
 54         return "姓名:"+this.name+",年龄:"+this.age+",出生日期:"+this.birth;
 55     }
 56 }
 57 
 58 class Age implements Cloneable{
 59     private int age;
 60     public Age(){}
 61     public Age(int age){
 62         this.age=age;
 63     }
 64     public Age clone(){
 65         Age obj=null;
 66         try {
 67             obj=(Age) super.clone();
 68         }catch (CloneNotSupportedException e){
 69             e.printStackTrace();
 70         }
 71         return obj;
 72     }
 73 
 74     public int getAge() {
 75         return age;
 76     }
 77 
 78     public void setAge(int age) {
 79         this.age = age;
 80     }
 81     public String toString(){
 82         return this.age+"";
 83     }
 84 }
 85 
 86 
 87 
 88 
 89 public class Demo2 {//浅拷贝-继承Cloneable接口实现
 90     public static void main(String[] args) {
 91         Person p1=new Person(new Age(18),"万雨",1995);
 92         Person p2=(Person)p1.clone();
 93         System.out.println(p1.toString());
 94         System.out.println(p2.toString());
 95 
 96         p1.setAge(17);
 97         p1.setBirth(2019);
 98         p1.setName("Mufasa");
 99 
100         System.out.println(p1.toString());
101         System.out.println(p2.toString());
102 
103     }
104 }
View Code

 

使用继承Serializable接口进行序列化与反序列化进行深拷贝【注意对象不能使用transient进行修饰,原因:transient修饰的对象无法进行序列化!】

 1 package com.cnblogs.mufasa.Demo3;
 2 
 3 
 4 import java.io.*;
 5 
 6 class Person implements Serializable{
 7     private Age age;
 8     private String name;
 9     private int birth;
10     public Person(Age age, String name,int birth) {
11         this.age = age;
12         this.name = name;
13         this.birth = birth;
14     }
15 
16     public Age getAge() {
17         return this.age;
18     }
19 
20     public void setAge(int age) {
21         this.age.setAge(age); ;
22     }
23 
24     public void setAge(Age age) {
25         this.age = age;
26     }
27 
28     public int getBirth() {
29         return birth;
30     }
31 
32     public void setBirth(int birth) {
33         this.birth = birth;
34     }
35 
36     public String getName() {
37         return this.name;
38     }
39 
40     public void setName(String name) {
41         this.name = name;
42     }
43     public String toString(){
44         return "姓名:"+this.name+",年龄:"+this.age+",出生日期:"+this.birth;
45     }
46 }
47 
48 class Age implements Serializable {
49     private int age;
50     public Age(){}
51     public Age(int age){
52         this.age=age;
53     }
54     public int getAge() {
55         return age;
56     }
57 
58     public void setAge(int age) {
59         this.age = age;
60     }
61     public String toString(){
62         return this.age+"";
63     }
64 }
65 
66 
67 
68 
69 public class Demo3 {//浅拷贝-继承Cloneable接口实现
70     public static void main(String[] args) throws IOException, ClassNotFoundException {
71         Person p1=new Person(new Age(18),"万雨",1995);
72 
73         ByteArrayOutputStream bos=new ByteArrayOutputStream();
74         ObjectOutputStream oos=new ObjectOutputStream(bos);
75 
76         oos.writeObject(p1);//1,先进行序列化
77         oos.flush();
78         ObjectInputStream ois=new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()));
79         Person p2=(Person)ois.readObject();//2,进行反序列化
80 
81 
82         System.out.println(p1.toString());
83         System.out.println(p2.toString());
84 
85         p1.setAge(17);
86         p1.setBirth(2019);
87         p1.setName("Mufasa");
88 
89         System.out.println(p1.toString());
90         System.out.println(p2.toString());
91 
92     }
93 }
View Code
姓名:万雨,年龄:18,出生日期:1995
姓名:万雨,年龄:18,出生日期:1995
姓名:Mufasa,年龄:17,出生日期:2019
姓名:万雨,年龄:18,出生日期:1995

 

posted on 2019-08-19 17:23  周健康  阅读(420)  评论(0编辑  收藏  举报

导航