Java序列化和反序列化(Serializable)

1. 序列化和反序列化

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

2. Serializable接口是什么

这是对象序列化接口,一个类只有实现了Serializable接口,它的对象才能被序列化。
Serializable接口就是Java提供用来进行高效率的异地共享实例对象的机制,实现这个接口即可。

3. 什么情况下需要序列化

当我们需要把对象的状态信息通过网络进行传输,或者需要将对象的状态信息持久化,以便将来使用时都需要把对象进行序列化

4. 测试

将java对象序列化并持久保存在文件中,再从文件中反序列化为对象的测试过程。

4.1 创建一个普通实体类(People)

Java序列化和反序列化(Serializable)_第1张图片

4.2 创建一个测试用序列化工具类(SerializableTools )
/**
 * 测试Serializable接口作用
 *
 * 1.在对没有实现Serializable接口,进行写入文件操作时会出现异常:java.io.NotSerializableException
 * 2.正常情况下:无论有无serialVersionUID字段,都不影响对象的序列化和反序列化,因为用户没有定义该字段时,jvm会自动创建一个值
 * 3.在没有定义serialVersionUID时,当已经对现在的对象进行了序列号存储,如果用户改变了类的变量个数、变量类型等情况会导致数据反序列化失败抛出异常:
 *   java.io.InvalidClassException:local class incompatible: stream classdesc serialVersionUID = -1914612148418344721, local class serialVersionUID = -8347405390320853159
 * 4.如果用户有自定义serialVersionUID字段的值,便不会出现第3点的情况,所以建议用户自定义serialVersionUID字段的值。
 */
public class SerializableTools {

    public static void main(String[] args) throws IOException {

        File file = new File("./common/src/main/java/com/study/serializable/test.txt");
        People people = new People();
        people.setId(1);
        people.setName("新风");
        people.setAge(23);
        System.out.println("序列化对象:"+people.toString());
        writeToFile(people,file);
        People p = readFromFile(file);
        System.out.println("反序列化结果:"+p.toString());

    }

    private static void writeToFile(People people, File file) throws IOException {

        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file));
        oos.writeObject(people);

    }

    private static People readFromFile(File file) throws IOException {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
        People p = null;
        try {
            p = (People) ois.readObject();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return p;
    }

}

4.3 测试过程

4.3.1 正常运行程序没有问题,运行结果:
Java序列化和反序列化(Serializable)_第2张图片

4.3.2 People去掉implements Serializable,运行程序时抛出异常:java.io.NotSerializableException,所以在对没有实现Serializable接口,进行写入文件操作时会出现异常,序列化失败。

4.3.3 还原上面的代码,分别运行注释掉People类中的第16行,和不注释结果都没有问题。所以正常情况下:无论有无serialVersionUID字段,都不影响对象的序列化和反序列化,因为用户没有定义该字段时,jvm会自动创建一个值。

4.3.4 先还原代码,然后注释掉People类的第16行和22行,运行程序将people序列化到test.txt中,然后取消People类的第22行注释并注释SerializableTools 类的第15-20行,再次运行程序则抛出异常: java.io.InvalidClassException:local class incompatible: stream classdesc serialVersionUID = -1914612148418344721, local class serialVersionUID = -8347405390320853159,所以,在没有定义serialVersionUID字段时,当已经对现在的对象进行了序列号存储,如果用户改变了类的变量个数、变量类型等情况会导致数据反序列化失败抛出异常。

4.3.5 还原代码,重复4.3.4的操作,但整个过程中People类的第16行注释,程序正常运行,这个过程中两次运行,相当于sex字段是新增字段,反序列化结果sex的值为null,所以建议用户自定义serialVersionUID字段的值。

学习参考: https://kuaibao.qq.com/s/20190512A08ICD00?function=liulanqi_feed&refer=liulanqi_feed_tl&kd_plan_id=LFA1-1&kd_content_id=20190512A08ICD00

你可能感兴趣的:(Java)