复制对象与复制引用

2019-08-08 00:00:00 对象 引用 复制
原型模式:(复制对象)
1.复制"引用"与复制"对象"的区别   1.1复制"引用"---复制地址   假设被复制对象为A a,复制的新对象为A b.   复制引用的过程就是将a的地址值复制给b.a和b同时指向堆内存的同一个地址. 过程为:
1 A a = new A(); 2 A b = a; 
这样,只要其中一个对象的属性发生变化,另一个对象的属性也随之发生变化.  
《复制对象与复制引用》
根据"复制引用"编写程序:
 1 public class Student {  2     
 3     public static void main(String[] args) {  4         Student s1 = new Student("张三", 23);  5         Student s2 = s1;  6         System.out.println(s1 == s2);  7  System.out.println(s1);  8  System.out.println(s2);  9         
10         //1.改变s1的名字
11         s1.setName("李四"); 12         System.out.println(s1 == s2); 13  System.out.println(s1); 14  System.out.println(s2); 15         
16         //1.改变s1的名字
17         s2.setName("王五"); 18         System.out.println(s1 == s2); 19  System.out.println(s1); 20  System.out.println(s2); 21  } 22     
23     private String name; 24     private int age; 25     
26     public Student() {} 27 
28     public Student(String name, int age) { 29         this.name = name; 30         this.age = age; 31  } 32 
33     public String getName() { 34         return name; 35  } 36 
37     public void setName(String name) { 38         this.name = name; 39  } 40 
41     public int getAge() { 42         return age; 43  } 44 
45     public void setAge(int age) { 46         this.age = age; 47  } 48 
49  @Override 50     public String toString() { 51         return "Student [name=" + name + ", age=" + age + "]"; 52  } 53 }
程序运行结果:
 1 true
 2 Student [name=张三, age=23]  3 Student [name=张三, age=23]  4 
 5 true
 6 Student [name=李四, age=23]  7 Student [name=李四, age=23]  8 
 9 true
10 Student [name=王五, age=23] 11 Student [name=王五, age=23]
1.2复制"对象"---复制内容
  假设被复制对象为Student s1,复制的新对象为Student s2.
  Student类有两个属性,name 和 age;
  复制对象的过程:
  ①:Student s1 = new Student("张三", 23);
  ②:Student s2 = new Student();
  ③:s2.setName(s1.getName());
     s2.setAge(s1.getAge());
  s1与s2是两个不同的对象,保存相同的属性及其属性值.当s1的属性值发生变化时,s2的属性值不会受到影响.s1与s2相互独立.
 《复制对象与复制引用》
根据"复制对象的过程"编写程序:
 1 public class Student {  2     
 3     public static void main(String[] args) {  4         Student s1 = new Student("张三", 23);  5         Student s2 = new Student();  6 
 7  s2.setName(s1.getName());  8  s2.setAge(s1.getAge());  9         System.out.println(s1 == s2); 10  System.out.println(s1); 11  System.out.println(s2); 12         
13         s1.setName("李四"); 14  System.out.println(s1); 15  System.out.println(s2); 16         
17         s2.setName("王五"); 18  System.out.println(s1); 19  System.out.println(s2); 20  } 21     
22     private String name; 23     private int age; 24     
25     public Student() {} 26 
27     public Student(String name, int age) { 28         this.name = name; 29         this.age = age; 30  } 31 
32     public String getName() { 33         return name; 34  } 35 
36     public void setName(String name) { 37         this.name = name; 38  } 39 
40     public int getAge() { 41         return age; 42  } 43 
44     public void setAge(int age) { 45         this.age = age; 46  } 47 
48  @Override 49     public String toString() { 50         return "Student [name=" + name + ", age=" + age + "]"; 51  } 52 }

 

程序运行结果:
1 false
2 Student [name=张三, age=23] 3 Student [name=张三, age=23] 4 
5 Student [name=李四, age=23] 6 Student [name=张三, age=23] 7 
8 Student [name=李四, age=23] 9 Student [name=王五, age=23]
2.原型模式
  2.1假设对象的属性特征很简单:(直接赋值,不需要new对象来赋值)
  例:情况1.
1 class Person{ 2     private String name; 3     private int age; 4 }
那么:实现对象复制的过程很简单.
思路A:
①:Person类实现Cloneable接口.
    Cloneable是一个标识性接口,没有抽象方法.实现这个接口的类被标记为可以被克隆.
②:Person类重写clone()方法.
根据思路A编写程序:
 1 public class Person implements Cloneable{  2     
 3     public static void main(String[] args) throws CloneNotSupportedException {  4         // 测试  5         //原型
 6             Person person = new Person("张三", 23);  7         //克隆对象
 8             Person clonePerson = (Person)person.clone();  9         System.out.println(person == clonePerson); 10  System.out.println(person); 11  System.out.println(clonePerson); 12         
13            //1.改变person的名字和对象
14         person.setName("李四"); 15         person.setAge(24); 16  System.out.println(person); 17  System.out.println(clonePerson); 18         
19             //2.改变clonePerson的名字和对象
20         clonePerson.setName("王五"); 21         clonePerson.setAge(25); 22  System.out.println(person); 23  System.out.println(clonePerson); 24  } 25 
26     private String name; 27     private int age; 28     public Person(String name, int age) { 29         this.name = name; 30         this.age = age; 31  } 32     public Person() {} 33     public String getName() { 34         return name; 35  } 36     public void setName(String name) { 37         this.name = name; 38  } 39     public int getAge() { 40         return age; 41  } 42     public void setAge(int age) { 43         this.age = age; 44  } 45  @Override 46     public String toString() { 47         return "Person [name=" + name + ", age=" + age + "]"; 48  } 49     public Object clone() throws CloneNotSupportedException { 50         Person person = (Person)super.clone(); 51         return person; 52  } 53 }
程序运行结果:
1 false
2 Person [name=张三, age=23] 3 Person [name=张三, age=23] 4 
5 Person [name=李四, age=24] 6 Person [name=张三, age=23] 7 
8 Person [name=李四, age=24] 9 Person [name=王五, age=25]

 

2.1假设对象的某些属性特征较复杂:(需要new对象来赋值)
例:情况2.
 1 class Person{  2     private String name;  3     private int age;  4     private Company com;  5 }  6 
 7 
 8 class Company{  9     private String name; 10     private int age; 11     private String address; 12 }
在情况2下能够采用思路A编程吗?
让我们来试一试:思路A
 1 public class Person implements Cloneable{  2     
 3     public static void main(String[] args) throws CloneNotSupportedException {  4         // 测试  5         //1.创建原型对象
 6         Company com = new Company("tencent", 5, "深圳");  7         Person person = new Person("张三", 23, com);  8         //原型克隆
 9         Person clonePerson = (Person)person.clone(); 10         System.out.println(person == clonePerson); 11  System.out.println(person); 12  System.out.println(clonePerson); 13         
14         //2.改变原型对象的com
15         Company personCom = person.getCom(); 16         personCom.setName("alibaba"); 17         personCom.setAge(3); 18         personCom.setAddress("杭州"); 19  System.out.println(person); 20  System.out.println(clonePerson); 21         
22         //3.改变克隆对象的com
23         Company clonePersonCom = clonePerson.getCom(); 24         clonePersonCom.setName("baidu"); 25         clonePersonCom.setAge(4); 26         clonePersonCom.setAddress("beijing"); 27  System.out.println(person); 28  System.out.println(clonePerson); 29  } 30 
31     private String name; 32     private int age; 33     private Company com; 34     
35     public Person() {} 36     
37     public Person(String name, int age, Company com) { 38         this.name = name; 39         this.age = age; 40         this.com = com; 41  } 42     
43     public String getName() { 44         return name; 45  } 46     public void setName(String name) { 47         this.name = name; 48  } 49     public int getAge() { 50         return age; 51  } 52     public void setAge(int age) { 53         this.age = age; 54  } 55     public Company getCom() { 56         return com; 57  } 58 
59     public void setCom(Company com) { 60         this.com = com; 61  } 62     
63  @Override 64     public String toString() { 65         return "Person [name=" + name + ", age=" + age + ", com=" + com + "]"; 66  } 67     public Object clone() throws CloneNotSupportedException { 68         Person person = (Person)super.clone(); 69         return person; 70  } 71 }

 

 1 public class Company implements Cloneable{  2 
 3     private String name;  4     private int age;  5     private String address;  6     public Company() {  7  }  8     public Company(String name, int age, String address) {  9         this.name = name; 10         this.age = age; 11         this.address = address; 12  } 13     public String getName() { 14         return name; 15  } 16     public void setName(String name) { 17         this.name = name; 18  } 19     public int getAge() { 20         return age; 21  } 22     public void setAge(int age) { 23         this.age = age; 24  } 25     public String getAddress() { 26         return address; 27  } 28     public void setAddress(String address) { 29         this.address = address; 30  } 31     
32  @Override 33     public String toString() { 34         return "Company [name=" + name + ", age=" + age + ", address=" + address + "]"; 35  } 36 }
程序运行结果:
1 false
2 Person [name=张三, age=23, com=Company [name=tencent, age=5, address=深圳]] 3 Person [name=张三, age=23, com=Company [name=tencent, age=5, address=深圳]] 4 
5 Person [name=张三, age=23, com=Company [name=alibaba, age=3, address=杭州]] 6 Person [name=张三, age=23, com=Company [name=alibaba, age=3, address=杭州]] 7 
8 Person [name=张三, age=23, com=Company [name=baidu, age=4, address=beijing]] 9 Person [name=张三, age=23, com=Company [name=baidu, age=4, address=beijing]]
这时会发现,已经有错误产生了.
当我们改动person或者clonePerson的com值时,另一个对象的com也会随之发生改变.
修改方法:思路B
①:Person, Company都要实现Cloneable接口.
②:在对Person对象进行克隆的同时也要对Company对象进行克隆.
根据思路B编写程序:
 1 public class Person implements Cloneable{  2     
 3     public static void main(String[] args) throws CloneNotSupportedException {  4         // 测试  5         //1.创建原型对象
 6         Company com = new Company("tencent", 5, "深圳");  7         Person person = new Person("张三", 23, com);  8         //原型克隆
 9         Person clonePerson = (Person)person.clone(); 10         System.out.println(person == clonePerson); 11  System.out.println(person); 12  System.out.println(clonePerson); 13         
14         //2.改变原型对象的com
15         Company personCom = person.getCom(); 16         personCom.setName("alibaba"); 17         personCom.setAge(3); 18         personCom.setAddress("杭州"); 19  System.out.println(person); 20  System.out.println(clonePerson); 21         
22         //3.改变克隆对象的com
23         Company clonePersonCom = clonePerson.getCom(); 24         clonePersonCom.setName("baidu"); 25         clonePersonCom.setAge(4); 26         clonePersonCom.setAddress("北京"); 27  System.out.println(person); 28  System.out.println(clonePerson); 29  } 30 
31     private String name; 32     private int age; 33     private Company com; 34     
35     public Person() {} 36     
37     public Person(String name, int age, Company com) { 38         this.name = name; 39         this.age = age; 40         this.com = com; 41  } 42     
43     public String getName() { 44         return name; 45  } 46     public void setName(String name) { 47         this.name = name; 48  } 49     public int getAge() { 50         return age; 51  } 52     public void setAge(int age) { 53         this.age = age; 54  } 55     public Company getCom() { 56         return com; 57  } 58 
59     public void setCom(Company com) { 60         this.com = com; 61  } 62     
63  @Override 64     public String toString() { 65         return "Person [name=" + name + ", age=" + age + ", com=" + com + "]"; 66  } 67     public Object clone() throws CloneNotSupportedException { 68         Person person = (Person)super.clone();//克隆Person
69         person.setCom((Company)com.clone());//克隆Company
70         return person; 71  } 72 }

 

 1 public class Company implements Cloneable{  2     
 3     private String name;  4     private int age;  5     private String address;  6     public Company() {  7  }  8     public Company(String name, int age, String address) {  9         this.name = name; 10         this.age = age; 11         this.address = address; 12  } 13     public String getName() { 14         return name; 15  } 16     public void setName(String name) { 17         this.name = name; 18  } 19     public int getAge() { 20         return age; 21  } 22     public void setAge(int age) { 23         this.age = age; 24  } 25     public String getAddress() { 26         return address; 27  } 28     public void setAddress(String address) { 29         this.address = address; 30  } 31     
32     public Object clone() throws CloneNotSupportedException{ 33         return (Company)super.clone(); 34  } 35     
36  @Override 37     public String toString() { 38         return "Company [name=" + name + ", age=" + age + ", address=" + address + "]"; 39  } 40 }
程序运行结果:
1 false
2 Person [name=张三, age=23, com=Company [name=tencent, age=5, address=深圳]] 3 Person [name=张三, age=23, com=Company [name=tencent, age=5, address=深圳]] 4 
5 Person [name=张三, age=23, com=Company [name=alibaba, age=3, address=杭州]] 6 Person [name=张三, age=23, com=Company [name=tencent, age=5, address=深圳]] 7 
8 Person [name=张三, age=23, com=Company [name=alibaba, age=3, address=杭州]] 9 Person [name=张三, age=23, com=Company [name=baidu, age=4, address=北京]
根据思路B我们可以得到两个相互独立的对象.
但是,又产生了新的问题:
若是在com中还有类似于Company的对象存在呢(内部还有很多属性和方法)?
若是在Person中也有很多类似于Company的对象存在呢?
若是继续采用思路B,写起来会非常麻烦,并且有可能会遗漏(某个对象也许没有被克隆的情况).
针对产生的新的问题,我们需要重新思考解决方案:思路C
  ①:Person, Company实现Serializable接口.
  ②:采用对象流创建Person对象.
根据思路C编写程序:
 1 import java.io.ByteArrayInputStream;  2 import java.io.ByteArrayOutputStream;  3 import java.io.IOException;  4 import java.io.ObjectInputStream;  5 import java.io.ObjectOutputStream;  6 import java.io.Serializable;  7 
 8 
 9 public class Person implements Serializable{ 10     
11     public static void main(String[] args) throws CloneNotSupportedException, ClassNotFoundException, IOException { 12         // 测试 13         //1.创建原型对象
14         Company com = new Company("tencent", 5, "深圳"); 15         Person person = new Person("张三", 23, com); 16         //原型克隆
17         Person copyPerson = person.getCopyPerson(); 18         System.out.println(person == copyPerson); 19  System.out.println(person); 20  System.out.println(copyPerson); 21         
22         //2.person改变com的值
23         Company personCom = person.getCom(); 24         personCom.setName("alibaba"); 25         personCom.setAge(5); 26         personCom.setAddress("杭州"); 27  System.out.println(person); 28  System.out.println(copyPerson); 29         
30         //3.copyPerson改变com的值
31         Company copyPersonCom = copyPerson.getCom(); 32         copyPersonCom.setName("baidu"); 33         copyPersonCom.setAge(3); 34         copyPersonCom.setAddress("北京"); 35  System.out.println(person); 36  System.out.println(copyPerson); 37  } 38 
39     private String name; 40     private int age; 41     private Company com; 42     
43     public Person() {} 44     
45     public Person(String name, int age, Company com) { 46         this.name = name; 47         this.age = age; 48         this.com = com; 49  } 50     
51     public String getName() { 52         return name; 53  } 54     public void setName(String name) { 55         this.name = name; 56  } 57     public int getAge() { 58         return age; 59  } 60     public void setAge(int age) { 61         this.age = age; 62  } 63     public Company getCom() { 64         return com; 65  } 66 
67     public void setCom(Company com) { 68         this.com = com; 69  } 70     
71  @Override 72     public String toString() { 73         return "Person [name=" + name + ", age=" + age + ", com=" + com + "]"; 74  } 75     
76     public Person getCopyPerson() throws IOException, ClassNotFoundException { 77         // 创建输出流
78         ByteArrayOutputStream bos = new ByteArrayOutputStream(); 79         ObjectOutputStream oos = new ObjectOutputStream(bos); 80         oos.writeObject(this); 81         
82         // 创建输入流
83         ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); 84         ObjectInputStream ois = new ObjectInputStream(bis); 85         Object obj = ois.readObject(); 86         return (Person)obj; 87  } 88 }
 1 import java.io.Serializable;  2 
 3 public class Company implements Serializable{  4 
 5     private static final long serialVersionUID = 1L;  6     private String name;  7     private int age;  8     private String address;  9     public Company() { 10  } 11     public Company(String name, int age, String address) { 12         this.name = name; 13         this.age = age; 14         this.address = address; 15  } 16     public String getName() { 17         return name; 18  } 19     public void setName(String name) { 20         this.name = name; 21  } 22     public int getAge() { 23         return age; 24  } 25     public void setAge(int age) { 26         this.age = age; 27  } 28     public String getAddress() { 29         return address; 30  } 31     public void setAddress(String address) { 32         this.address = address; 33  } 34     
35  @Override 36     public String toString() { 37         return "Company [name=" + name + ", age=" + age + ", address=" + address + "]"; 38  } 39 }
程序运行结果:
1 false
2 Person [name=张三, age=23, com=Company [name=tencent, age=5, address=深圳]] 3 Person [name=张三, age=23, com=Company [name=tencent, age=5, address=深圳]] 4 
5 Person [name=张三, age=23, com=Company [name=alibaba, age=5, address=杭州]] 6 Person [name=张三, age=23, com=Company [name=tencent, age=5, address=深圳]] 7 
8 Person [name=张三, age=23, com=Company [name=alibaba, age=5, address=杭州]] 9 Person [name=张三, age=23, com=Company [name=baidu, age=3, address=北京]]

相关文章