您的位置:首页 > 编程语言 > Java开发

233_尚学堂_高淇_java300集最全视频教程_【GOF23设计模式】_原型模式_prototype_浅复制_深复制_反序列化实现深复制

2015-06-15 22:55 931 查看
原型模式分为深复制和浅复制

浅复制:只是拷贝对象本身,不拷贝对象的属性,所以”浅“。复制后的对象自然在内存中位于不同的地址中,因为本质上是两个对象,所以内存中的地址自然不同。但是复制之后的对象的属性却与原对象的属性相同,也就是两个对象的属性在内存中位于同一地址,并没有拷贝出另一份。复制(或者说拷贝)的意思是生成了另外的对象,只是复制对象本身,说明生成了本质上别的对象,在内存中另一个地方,没有复制对象的属性,说明两个对象的属性在内存中同一地方。

深赋值:既复制了对象本身,也复制了对象的属性,也就是说复制后的对象的属性在内存中的另外的地址中,尽管另外的地址中的内容跟原对象的相同。

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 原型模式