序列化(Serialization)实现深拷贝

本文深入探讨了深拷贝的概念及其在Java中的实现方法,特别是通过序列化和反序列化实现深度克隆的过程,包括如何处理内层引用类型和序列化注意事项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

  深拷贝:指的是拷贝一个对象时,不仅仅把对象的引用进行复制,还把该对象引用的值也一起拷贝。如果引用类型里面还包含很多引用类型,或者内层引用类型的类里面又包含多层引用类型,那么通过clone()方法逐一拷贝每一个引用类型来实现深拷贝的方法就会很麻烦。这时我们可以用序列化来实现对象的深拷贝。

序列化简介

  序列化就是将对象写到流中的过程,写到流中的对象是原有对象的一个拷贝,而原对象仍然存在于内存中。通过序列化实现的拷贝不仅可以复制对象本身,而且可以复制其引用的成员对象,因此通过序列化将对象写到一个流中,再从流中将其读出来,即可实现深拷贝。需要注意的是序列化对象的类必须实现Serializable接口,否则无法实现序列化操作。

  Java语言提供的Cloneable接口和Serializable接口的代码非常简单,它们都是空接口,这种空接口也称为标识接口,标识接口中没有任何方法的定义,其作用是告诉JRE这些接口的实现类是否具有某个功能,实现或不实现就是该功能的体现,如是否支持克隆、是否支持序列化等。

例:使用序列化深拷贝一个学生类对象

public class Student implements Serializable{
  private String name;
  public Address address;
 //Discription:[深度复制方法,需要对象及对象所有的对象属性都实现序列化] 
  public Student myclone() {
      Student stu = null;
      try { // 将该对象序列化成流,因为写在流里的是对象的一个拷贝,而原对象仍然存在于JVM里面。所以利用这个特性可以实现对象的深拷贝
          ByteArrayOutputStream baos = new ByteArrayOutputStream();
          ObjectOutputStream oos = new ObjectOutputStream(baos);
          oos.writeObject(this);
      // 再将流序列化成对象
          ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
          ObjectInputStream ois = new ObjectInputStream(bais);
          stu = (Student) ois.readObject();
      } catch (IOException e) {
          e.printStackTrace();
      } catch (ClassNotFoundException e) {
          e.printStackTrace();
      }
      return stu;
  }
}

内层引用Address也必须实现Serializable,否则无法序列化

public class Address implements Serializable{
  private String add;

public Address(String add) {
      this.add= add;
  }
}
注意

   1. 基于序列化和反序列化实现的克隆不仅仅是深拷贝,更重要的是通过泛型限定,可以检查出要克隆的对象是否支持序列化,这项检查是编译时期完成的,让问题在编译的时候暴露出来总是优于把问题留到运行时,这种是方案明显优于使用Object类的clone方法克隆对象的。

   2. 如果序列化对象的时候,不希望其某个属性被序列化,可以在该属性前添加transient关键字,这样,这个该属性就不会序列化到指定的目的地中,或者在该属性前添加static关键字,因为序列化保存的是对象的状态,而静态变量属于的状态,因此序列化并不保存静态变量。

总结

  实现对象克隆有两种方式:

1). 实现Cloneable接口并重写Object类中的clone()方法;

2). 实现Serializable接口,通过对象的序列化和反序列化实现克隆,这种方式才是真正意义上的的深度克隆。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值