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 }
姓名:万雨,年龄: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 }
使用继承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 }
姓名:万雨,年龄: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 }
使用继承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 }
姓名:万雨,年龄:18,出生日期:1995 姓名:万雨,年龄:18,出生日期:1995 姓名:Mufasa,年龄:17,出生日期:2019 姓名:万雨,年龄:18,出生日期:1995
探究未知是最大乐趣