Java基础 - 序列化 与 反序列化 - 2020年6月

一、阶段之“用”

package com.kevin.springbootkevin1.javamain;
import java.io.*;
public class Serialize {
    //序列化 - 将Java对象转化为字节流 - 保存到stu.txt
    public void Serialize() throws IOException {
        Student student = new Student("kevin" , 21);
        ObjectOutputStream objectOutputStream  = new ObjectOutputStream(
                new FileOutputStream(
                        new File("./stu.txt")));
        objectOutputStream.writeObject(student);
        objectOutputStream.close();
        System.out.println("序列化...生成stu.txt成功!");
    }

    //反序列化 - 将字节流转化为Java对象 - 从stu.txt中读取字节流
    public void DeSerialize() throws IOException, ClassNotFoundException {
        ObjectInputStream objectInputStream = new ObjectInputStream(
                new FileInputStream(
                        new File("./stu.txt")));
        Student student = new Student();
        student = (Student) objectInputStream.readObject();
        System.out.println("反序列化...Student = " + student);
    }

    //需要注意的是:这里抛出了IOException, ClassNotFoundException两个异常
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        new Serialize().Serialize();
        new Serialize().DeSerialize();
    }
}

运行结果:

序列化: Java对象转化为字节序列

反序列化:字节序列转化为Java对象

二、阶段之“理解原理”

(1)若对象类未实现Serialize接口,则会报异常

因此,我们进入Serialize接口发现: 该接口无其他任何方法!

接着,我们进入objectOutputStream发现,WriteObject方法中: 

若传入的对象:

1. 实现了Serialize接口:则会正常调用写入函数进行下一步操作;

2. 既未实现字符串、数组、枚举、也未实现Serialize接口,则:抛出NotSerilazableException异常。

3. 是字符串或数组或枚举类型,则也会正常调用写入函数进行下一步操作;

 

综上: 在对象类implement Serialize类,并不会起到具体实质的作用,而我们可以把它看成是一种需要被序列化的标记。

(2)问:serialVersionUID有什么用?

这里,我们先举例说明:

1. 先对Student类不设置serialVersionUID , 然后对该Student对象进行序列化。

2. 然后改变Student类结构( 给Student类加一个属性t ) 

3.对刚刚序列化后的stu.txt的内容,进行反序列化。

4. 出现报错

综上,有以下结论:

A.   serialVersionUID 是进行序列前后的唯一标识。

B.   若不手动设置serialVersionUID , 编译器会为它自动声明一个。

C.   serialVersionUID自动生成的值与 类的 结构和属性有关!

说明:

serialVersionUID相当于是序列化和反序列化的“暗号”,JVM将字节流中的serialVersionUID与被序列化中设置的serialVersionUID进行比对;如果比对不一致,则会报错java.io.InvalidClassException。

写代码时,最好手动设置一个serialVersionUID值。

(3)防止对象的某字段被实例化,有两种方法:

1. 使用static关键字:序列化保存的是对象的状态(而不是类的状态),忽略静态域中的变量数据。

 

 

2. 被transient修饰的字段不会被序列化:

而对于transient修饰符:

java的serialization提供了一个非常棒的存储对象状态的机制, serialization就是把对象的状态存储到硬盘上。 

transient的作用就是把这个字段的生命周期仅存于调用者的内存中不会写到磁盘里持久化.

 

 

 

全部评论

相关推荐

点赞 收藏 评论
分享
牛客网
牛客企业服务