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

java序列化与反序列化(4)------jdk原生序列化机制实现深拷贝

2017-10-06 15:57 399 查看
简单地说所谓深拷贝就是将对象域为引用指向的内存中对象,在内存中再创建一份赋值给深拷贝出的新对象。

(1) 实现Cloneable接口的深拷贝

我们先看之前执行深拷贝的方法,直接上代码:

/**
* 实现Cloneable接口,并重写clone方法
* @author yujie.wang3
*
*/
public class Book implements Cloneable{
private int page;

private String name;

private Owner owner;

public Book(){
System.out.println("invoke Book()");
}
public Book(int page, String name, Owner owner) {
this.page = page;
this.name = name;
this.owner = owner;
System.out.println("invoke Book(int page, String name, Owner owner)");
}

public Owner getOwner() {
return owner;
}

public void setOwner(Owner owner) {
this.owner = owner;
}

public int getPage() {
return page;
}

public void setPage(int page) {
this.page = page;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

/**
* 这里执行深拷贝
*/
@Override
public Object clone() {
// TODO Auto-generated method stub
Book b = null;
try {
b = (Book)super.clone();
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
b.owner = (Owner)owner.clone();
return b;
}
}

/**
* 实现Cloneable接口,并重写clone方法
* @author yujie.wang
*
*/
public class Owner implements Cloneable{
private int age;

private String name;

public Owner(){
System.out.println("invoke Owner()");
}

public Owner(int age, String name) {
this.age = age;
this.name = name;
System.out.println("Owner(int age, String name)");
}

/**
* 这里执行克隆拷贝
*/
@Override
public Object clone(){
// TODO Auto-generated method stub
Owner owner = null;
try {
owner = (Owner)super.clone();
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return owner;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

@Override
public String toString() {
return "Owner [age=" + age + ", name=" + name + "]";
}

}

测试代码如下:
/**
* 深拷贝测试类
* @author yujie.wang
*
*/
public class Test {
public static void main(String [] args){
Owner owner = new Owner(20,"yujie");
Book b1 = new Book(100,"thinking in java",owner);
// b1执行深拷贝给b2,其中b2中owner域为新的对象不同于上面那个owner的指向
Book b2 = (Book)b1.clone();
System.out.println(b1.getName() + " " + b1.getPage() + " " + b1.getOwner().toString());
System.out.println(b2.getName() + " " + b2.getPage() + " " + b2.getOwner().toString());
b1.setName("network");
b1.setPage(200);
// 这里b1的owner指向的对象状态发生改变,但是不影响b2中owner域
owner.setAge(22);
owner.setName("kobe");
System.out.println(b1.getName() + " " + b1.getPage() + " " + b1.getOwner().toString());
System.out.println(b2.getName() + " " + b2.getPage() + " " + b2.getOwner().toString());
}

}


运行测试代码输出结果如下:
Owner(int age, String name)
invoke Book(int page, String name, Owner owner)
thinking in java 100 Owner [age=20, name=yujie]
thinking in java 100 Owner [age=20, name=yujie]
network 200 Owner [age=22, name=kobe]
thinking in java 100 Owner [age=20, name=yujie]

从输出结果中我们看到b1的owner引用内容修改之后并没有影响b2的owner域,这说明深拷贝成功。
当然有一个现象就是,在执行深拷贝创建一个新对象的时候并没有调用任何构造函数。

(2)实现Serializable,Cloneable接口的深拷贝

如果需要执行深拷贝的类中有大量的引用存在,那么需要对每个引用都要实现Cloneable接口并重写clone方法,这看起来是一个十分繁琐的事情,当然其实还有一种方法比较简便就是使用序列化机制来实现深拷贝。

我们改造上面的代码:

/**
* 实现Serializable,Cloneable接口,并重写clone方法
* @author yujie.wang3
*
*/
public class Book implements Serializable,Cloneable{
private int page;

private String name;

private Owner owner;

public Book(){
System.out.println("invoke Book()");
}
public Book(int page, String name, Owner owner) {
this.page = page;
this.name = name;
this.owner = owner;
System.out.println("invoke Book(int page, String name, Owner owner)");
}

public Owner getOwner() {
return owner;
}

public void setOwner(Owner owner) {
this.owner = owner;
}

public int getPage() {
return page;
}

public void setPage(int page) {
this.page = page;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

/**
* 这里通过序列化执行深拷贝
*/
@Override
public Object clone() {
// TODO Auto-generated method stub
Object o = null;
try {
ByteArrayOutputStream bout = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(bout);
out.writeObject(this);
out.close();
ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
ObjectInputStream in = new ObjectInputStream(bin);
o = in.readObject();
in.close();
bin.close();
bout.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return o;
}
}

/**
* 实现Serializable标记接口
* @author yujie.wang
*
*/
public class Owner implements Serializable{
private int age;

private String name;

public Owner(){
System.out.println("invoke Owner()");
}

public Owner(int age, String name) {
this.age = age;
this.name = name;
System.out.println("Owner(int age, String name)");
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

@Override
public String toString() {
return "Owner [age=" + age + ", name=" + name + "]";
}

}


测试类不用改变,运行测试代码输出如下结果:
Owner(int age, String name)
invoke Book(int page, String name, Owner owner)
thinking in java 100 Owner [age=20, name=yujie]
thinking in java 100 Owner [age=20, name=yujie]
network 200 Owner [age=22, name=kobe]
thinking in java 100 Owner [age=20, name=yujie]

这个输出结果和第一种方式一样,但是同样有一个现象就是通过序列化机制创建对象的时候也没有调用任何构造函数。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐