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;
}
}
测试类不用改变,运行测试代码输出如下结果:
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]
这个输出结果和第一种方式一样,但是同样有一个现象就是通过序列化机制创建对象的时候也没有调用任何构造函数。
(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]
这个输出结果和第一种方式一样,但是同样有一个现象就是通过序列化机制创建对象的时候也没有调用任何构造函数。
相关文章推荐
- java序列化与反序列化(3)------jdk原生序列化机制Externalizable
- java序列化与反序列化(2)------jdk原生序列化机制Serializable
- [编写高质量代码:改善java程序的151个建议]建议43 避免对象浅拷贝; 建议44:推荐使用序列化实现对象的深拷贝
- java提高篇(五)-----使用序列化实现对象的拷贝
- java提高篇(五)-----使用序列化实现对象的拷贝
- java 的对象拷贝(有深浅拷贝两种方式,深拷贝实现的两种方式(逐层实现cloneable接口,序列化的方式来实现))
- java提高篇(六)_使用序列化实现对象的拷贝 转自 http://cmsblogs.com
- java提高篇-----使用序列化实现对象的拷贝
- Java 深拷贝和浅拷贝 利用序列化实现深拷贝
- Java利用序列化实现对象的深拷贝
- Java提高篇(五):使用序列化实现对象的拷贝
- JAVA中实现原生的 socket 通信机制原理
- Java 深拷贝和浅拷贝 利用序列化实现深拷贝
- Java序列化以及其实现机制
- java提高篇(六)-----使用序列化实现对象的拷贝
- java提高篇(五)-----使用序列化实现对象的拷贝
- java提高篇(五)-----使用序列化实现对象的拷贝
- 由service层接口有什么用?引申到基于JDK原生和CGLIB动态代理实现spring事务管理的机制的思考
- Java深拷贝除了通过实现Cloneable接口,另外还可以通过序列化实现对象的拷贝。
- Java序列化技术性能分析(JDK原生与Protostuff)