复制对象与复制引用
程序员文章站
2022-04-29 17:51:54
原型模式:(复制对象) 1.复制"引用"与复制"对象"的区别 1.1复制"引用"---复制地址 假设被复制对象为A a,复制的新对象为A b. 复制引用的过程就是将a的地址值复制给b.a和b同时指向堆内存的同一个地址. 过程为: 1 A a = new A(); 2 A b = a; 这样,只要其中... ......
原型模式:(复制对象) 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=北京]]