复制对象与复制引用
原型模式:(复制对象)
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=北京]]
相关文章