使用序列化与反序列化实现深拷贝

前言

深拷贝:在进行赋值之前,为指针类型的数据成员另辟了一个独立的内存空间,实现真正内容上的拷贝 。这种拷贝称为深拷贝。

深拷贝的两种实现方式

  1. 实现Cloneable接口,重写Object类中clone()方法,实现层层克隆的方法。
  2. 通过序列化(Serializable)的方法,将对象写到流里,然后再从流中读取出来。虽然这种方法效率很低,但是这种方法才是真正意义上的深度克隆。

序列化与反序列化

序列化:把对象转换为字节序列的过程称为对象的序列化。
反序列化:把字节序列恢复为对象的过程称为对象的反序列化。

实例

  1. 先构造一个学生对象。值得注意的是,被序列化的对象的类同样也必须要实现Serializable接口,否则将会抛出NotSerializableException异常。

    import java.io.Serializable;
    
    /**
     * @author CodeLuo
     * @date 2021/7/7 22:20
     */
    public class Student implements Serializable{
        private String name;
        private String address;
        private String sex;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getAddress() {
            return address;
        }
    
        public void setAddress(String address) {
            this.address = address;
        }
    
        public String getSex() {
            return sex;
        }
    
        public void setSex(String sex) {
            this.sex = sex;
        }
    
        @Override
        public String toString() {
            return "Student{" +
                    "name='" + name + '\'' +
                    ", address='" + address + '\'' +
                    ", sex='" + sex + '\'' +
                    '}';
        }
    }
    复制代码
  2. 然后创建实现深拷贝的类StudentClone.java

    import java.io.*;
    
    /**
     * @author CodeLuo
     * @date 2021/7/7 22:17
     */
    public class StudentClone implements Serializable {
        public static Student myClone(Student student){
            Student anotherStu = null;
            try {
                //在内存中开辟一块缓冲区,将对象序列化成流
                ByteArrayOutputStream bout = new ByteArrayOutputStream();
                ObjectOutputStream out = new ObjectOutputStream(bout);
                out.writeObject(student);
    
                //找到这一块缓冲区,将字节流反序列化成另一个对象
                ByteArrayInputStream bais = new ByteArrayInputStream(bout.toByteArray());
                ObjectInputStream ois = new ObjectInputStream(bais);
                anotherStu = (Student) ois.readObject();
            } catch (IOException | ClassNotFoundException e) {
                e.printStackTrace();
            }
            return anotherStu;
        }
    }
    复制代码

    测试

    ​ 测试方法就是创建一个student对象和一个空对象,通过调用拷贝方法将student的属性深拷贝到anotherStudnet。

     public static void main(String[] args) {
            Student student = new Student();
            student.setName("张三");
            student.setAddress("地球");
            student.setSex("男");
            System.out.println("第一个学生:"+student);
    
            Student anotherStudent = null;
            System.out.println("深拷贝前的第二个学生:"+anotherStudent);
    
            anotherStudent = myClone(student);
            System.out.println("深拷贝后的第二个学生:"+anotherStudent);
        }
    复制代码

    测试结果

    ​ 程序运行后,测试出的结果如下图所示,成功完成拷贝。

image-20210707225631028.png

注意

  1. 若序列化对象的类中不实现Serializable接口,就会出现上诉中出现的NotSerializableException异常。如下图所示。

image-20210707230256349.png

  1. 如果说在业务需求方面,不希望对象的某个属性被序列化。比如说涉及敏感的的身份证号或者手机号码。当然敏感信息也可以做加密处理,哈哈。说会正题,这种情况下可以通过在属性前添加transient关键字。

        private String name;
        private String address;
        //假设这次不希望性别被复制过去。
        private transient String sex;
    复制代码

image-20210707230809245.png

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享