233_尚学堂_高淇_java300集最全视频教程_【GOF23设计模式】_原型模式_prototype_浅复制_深复制_反序列化实现深复制
2015-06-15 22:55
931 查看
原型模式分为深复制和浅复制
浅复制:只是拷贝对象本身,不拷贝对象的属性,所以”浅“。复制后的对象自然在内存中位于不同的地址中,因为本质上是两个对象,所以内存中的地址自然不同。但是复制之后的对象的属性却与原对象的属性相同,也就是两个对象的属性在内存中位于同一地址,并没有拷贝出另一份。复制(或者说拷贝)的意思是生成了另外的对象,只是复制对象本身,说明生成了本质上别的对象,在内存中另一个地方,没有复制对象的属性,说明两个对象的属性在内存中同一地方。
深赋值:既复制了对象本身,也复制了对象的属性,也就是说复制后的对象的属性在内存中的另外的地址中,尽管另外的地址中的内容跟原对象的相同。
因为s2的date进行了深复制,所以s2的date跟s1的虽然开始时间值相同,但是是不同的对象,所以改变s1的date的时间之后,s2的date的时间并没有变化。
因为s2的birthday是浅赋值,s2的birthday与s1的birthday是同一个对象,所以改变了s1的birthday后s2的birthday自然会变化。
这里注意一个问题:
这里s1在设置时间的时候,并不是改变原来的对象的时间值,而是让s1的date和birthday指向其他的对象,原来的对象没有变化,所以改了s1之后s2并不会变化,所以输出结果无论是深复制还是浅赋值,s1和s2的结果都是不同的。
通过反序列化实现深复制,不需要在clone方法中手动写深复制需要的代码。例程如下:
浅复制:只是拷贝对象本身,不拷贝对象的属性,所以”浅“。复制后的对象自然在内存中位于不同的地址中,因为本质上是两个对象,所以内存中的地址自然不同。但是复制之后的对象的属性却与原对象的属性相同,也就是两个对象的属性在内存中位于同一地址,并没有拷贝出另一份。复制(或者说拷贝)的意思是生成了另外的对象,只是复制对象本身,说明生成了本质上别的对象,在内存中另一个地方,没有复制对象的属性,说明两个对象的属性在内存中同一地方。
深赋值:既复制了对象本身,也复制了对象的属性,也就是说复制后的对象的属性在内存中的另外的地址中,尽管另外的地址中的内容跟原对象的相同。
public class Sheep01 implements Cloneable{ private Date date; private String name; private Date birthday; public Sheep01(){ } public Sheep01(Date date, String name, Date birthday) { this.date = date; this.name = name; this.birthday = birthday; } @Override protected Object clone() throws CloneNotSupportedException { Sheep01 s = (Sheep01) super.clone(); s.date = (Date) this.date.clone(); //对date这个属性进行了深复制 //birthday这个属性并没有深复制 return s; } public Date getDate() { return date; } public void setDate(Date date) { this.date = date; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } }
public class Demo01 { public static void main(String[] args) throws CloneNotSupportedException { //正确示例 Date date1 = new Date(); Date date2 = new Date(); Sheep01 s1 = new Sheep01(date1, "hah", date2); Sheep01 s2 = (Sheep01) s1.clone(); date1.setTime(234234234234L); date2.setTime(3423424234243L); System.out.println(s1.getDate()+"====="+s2.getDate()); System.out.println(s1.getBirthday()+"====="+s2.getBirthday()); } } /* 结果: s1:Sat Jun 04 09:03:54 CST 1977=====s2:Mon Jun 15 22:48:45 CST 2015 s1:Sun Jun 26 07:10:34 CST 2078=====s2:Sun Jun 26 07:10:34 CST 2078 */
因为s2的date进行了深复制,所以s2的date跟s1的虽然开始时间值相同,但是是不同的对象,所以改变s1的date的时间之后,s2的date的时间并没有变化。
因为s2的birthday是浅赋值,s2的birthday与s1的birthday是同一个对象,所以改变了s1的birthday后s2的birthday自然会变化。
这里注意一个问题:
public class Demo01 { public static void main(String[] args) throws CloneNotSupportedException { //错误示例,set的时候,不能new新的对象 Sheep01 s1 = new Sheep01(new Date(), "hah", new Date(1121212121L)); Sheep01 s2 = (Sheep01) s1.clone(); s1.setDate(new Date(333223223L)); s1.setBirthday(new Date(45645454534L)); System.out.println(s1.getDate()+"====="+s2.getDate()); System.out.println(s1.getBirthday()+"====="+s2.getBirthday()); } } /* 结果: s1:Mon Jan 05 04:33:43 CST 1970=====s2:Mon Jun 15 22:52:23 CST 2015 s1:Sun Jun 13 15:17:34 CST 1971=====s2:Wed Jan 14 07:26:52 CST 1970 */
这里s1在设置时间的时候,并不是改变原来的对象的时间值,而是让s1的date和birthday指向其他的对象,原来的对象没有变化,所以改了s1之后s2并不会变化,所以输出结果无论是深复制还是浅赋值,s1和s2的结果都是不同的。
通过反序列化实现深复制,不需要在clone方法中手动写深复制需要的代码。例程如下:
import java.io.Serializable; import java.util.Date; public class Sheep02 implements Cloneable, Serializable{ private Date date; private String name; private Date birthday; public Sheep02(){ // TODO Auto-generated constructor stub } public Sheep02(Date date, String name, Date birthday) { super(); this.date = date; this.name = name; this.birthday = birthday; } @Override protected Object clone() throws CloneNotSupportedException { // TODO Auto-generated method stub Sheep02 s = (Sheep02) super.clone(); return s; } public Date getDate() { return date; } public void setDate(Date date) { this.date = date; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } } /** * 通过反序列化实现深复制,用到两种IO流 * @author Hong * */ public class Demo02 { public static void main(String[] args) throws Exception { Date date = new Date(); Sheep02 s = new Sheep02(); s.setDate(date); System.out.println("s: "+s.getDate()); //os可以将对象转换成输出流,同时bao可以获得这个输出流,并且可以转化成字节数组 ByteArrayOutputStream bao = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bao); oos.writeObject(s); byte[] b = bao.toByteArray(); //bai可以将字节数组转化成输入流,ois可以获得这个输入流,并且将输入流转化成对象 ByteArrayInputStream bai = new ByteArrayInputStream(b); ObjectInputStream ois = new ObjectInputStream(bai); Sheep02 s2 = (Sheep02) ois.readObject(); System.out.println("s2: "+s2.getDate()); date.setTime(23232323232L); System.out.println("s: "+s.getDate() +"----s2: "+s2.getDate()); } } /** 运行结果: s: Thu Jun 18 21:01:56 CST 2015 s2: Thu Jun 18 21:01:56 CST 2015 s: Sun Sep 27 05:25:23 CST 1970----s2: Thu Jun 18 21:01:56 CST 2015 **/
相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- Android IPC进程间通讯机制
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- 介绍一款信息管理系统的开源框架---jeecg
- 聚类算法之kmeans算法java版本
- java实现 PageRank算法
- PropertyChangeListener简单理解
- 插入排序
- 冒泡排序
- 堆排序
- 快速排序
- 二叉查找树
- [原创]java局域网聊天系统