Serializable序列化和反序列化总结

一、关于serializableUID
反序列化的时候serializableUID要跟序列化的保持一致,反序列化才会成功,如果序列化和反序列化都没有serializableUID也是可行的。
序列化和反序列化修改文件时需要注意的点:
1、如果序列化对象的serializableUID是用集成工具自动生成的,序列化对象的时候用了这个serializableUID,反序列化之前如果把序列化对象的serializableUID去掉的话,反序列化是可以成功的,因为默认会自动生成一个一模一样的serializableUID;如果序列化对象的时候自己设定一个serializableUID,反序列化之前把这个serializableUID去掉了,反序列化就不会成功,因为反序列化默认生成的serializableUID跟序列化的serializableUID不一致。
2、当不指定serializableUID的时候,即使反序列化之前对这个对象增加空格和换行,反序列化也是可以成功的,因为这两步操作生成的serializableUID是一样的,但是如果反序列化之前对象中添加了一些属性,则不会反序列化成功,因为serializableUID的生成方法是根据对象的属性生成的,两步操作serializableUID不一致。
3、当指定serializableUID的时候,序列化以后,给对象增加新的属性,反序列化是可以成功的,只不过新增的属性的值为null。
二、关于静态成员
1、静态变量是不能够被序列化的,静态成员是随着类的加载而加载的,与类共存亡的,而序列化是针对对象的。
(1)测试过程如下:首先在类里面设置一个静态变量age,比如设置初始值为5,序列化写入文件(比如Test.txt)之前给这个静态重新赋值为3,然后运行main方法开始序列化;序列化以后,开始反序列化,也是运行main方法,会发现这个静态变量age打印出来的值为5,而不是3。
(2)可能存在的坑:运行main方法的时候,序列化和反序列化不要一起运行,一起运行的话,这样序列化加载类的时候,JVM首先会把静态变量age初始化为5,后面重新赋值为3,反序列化的时候,因为是同一个进程,会直接从JVM中获取静态变量age=3,所以最后打印的值是3。如果序列化和反序列化分开运行的话,序列化方法main执行,启动JVM,age=3,main执行完毕,此时JVM退出;反序列化main开始执行,重新启动JVM,加载类,初始化,age=5,main执行完毕,JVM退出,打印的值age=5。
三、关于父类、子类
1、如果父类实现了Serializable,子类不用实现,会自动进行序列化。
2、如果父类没实现Serializable,子类实现Serializable,只能进行子类的序列化,父类不会序列化。

四、利用序列化实现深克隆

public class Student implements Serializable{
    
    private static final long serialVersionUID = -6100391738494786200L;

    private String name;

    private int age;

    private Teacher teacher;

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

    public Teacher getTeacher() {
        return teacher;
    }

    public void setTeacher(Teacher teacher) {
        this.teacher = teacher;
    }

    public Object deepClone() throws IOException, ClassNotFoundException {
        //序列化
        ByteArrayOutputStream baos=new ByteArrayOutputStream();
        ObjectOutputStream oos=new ObjectOutputStream(baos);
        oos.writeObject(this);

        //反序列化
        ByteArrayInputStream bais=new ByteArrayInputStream(baos.toByteArray());
        ObjectInputStream ois=new ObjectInputStream(bais);
        return ois.readObject();
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", teacher=" + teacher +
                '}';
    }
}

public class Teacher implements Serializable {

    private static final long serialVersionUID = 8389453983965559287L;

    private String name;

    private String sex;

    public String getName() {
        return name;
    }

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

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    @Override
    public String toString() {
        return "Teacher{" +
                "name='" + name + '\'' +
                ", sex='" + sex + '\'' +
                '}';
    }
}
public class SerializableCloneDemo {
    
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        Teacher teacher=new Teacher();
        teacher.setName("老师");
        teacher.setSex("女");

        Student student=new Student();
        student.setName("学生");
        student.setAge(18);
        student.setTeacher(teacher);

        Student student1=(Student)student.deepClone();
        student1.getTeacher().setName("老师111");
        System.out.println(student);
        System.out.println(student1);

    }
}

由结果可以看出实现了深克隆:Student引用Teacher,student1修改Teacher的属性,并没有影响原来的Student里面的Teacher对象,由此可见,student和student1的teacher的引用并不是同一个对象,而深克隆不仅要把原有对象的变量都复制一份,而且原有对象所引用的对象都复制了一遍。

Serializable补充:
1、关键字transient加到对象哪个属性前面,哪个属性就不被序列化。
2、如果一个对象A引用对象B,如果对象A进行序列化,会自动也把对象B进行序列化,前提是A和B都要实现Serializable才可以。


水平有限,希望读者多多批评指正,感谢!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值