复制对象与复制引用

原型模式:(复制对象)
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=北京]]
posted @ 2019-06-11 20:22  helar  阅读(1030)  评论(0编辑  收藏  举报