首页 > 编程知识 正文

Java 序列化与反序列化,java反序列

时间:2023-05-04 18:44:12 阅读:229176 作者:2245

Java 序列化与反序列化

文章目录 Java 序列化与反序列化1 序列化与反序列化的概念2 核心类与关键字总览3 序列化与反序列化的过程3 应用示例4 序列化版本号的作用 serialVersionUID5 transient 关键字6 序列化的好处及应用场景7 序列化注意事项

1 序列化与反序列化的概念

Java 序列化是指:将对象转化成一个字节序列(二进制数据)的过程。

将序列化对象写入文件之后,可以从文件中读取出来,并且对它进行反序列化。

Java 反序列化是指:将一个对象的字节序列恢复成 Java 对象的过程。

一个平台中序列化的对象,可以在另一个平台中进行反序列化,因为这个过程是在 JVM 中独立完成的,可以依赖于 Java 的可移植性。

2 核心类与关键字总览

ObjectOutputStream:IO 类,包含序列化对象的方法,writeObject()

ObjectInputStream:IO 类,包含反序列化对象的方法,readObject()

上面两个 IO 流类是高层次的数据库,需要借助文件流进行序列化与反序列化操作。

Serializable ,接口,是一个标志性接口,标识可以在 JVM 中进行序列化,JVM 会为该类自动生成一个序列化版本号。参与序列化与反序列化的类必须实现 Serializable 接口。

serialVersionUID,类属性,序列化版本号,用于给 JVM 区别同名类,没有提供版本号,JVM会默认提供序列化版本号。

transient,关键字,当序列化时,不希望某些属性参与,则可以使用这个关键字标注该属性。

3 序列化与反序列化的过程

内存中的数据信息被拆分成一小块一小块的部分,为每个小块设置编号,然后存放到硬盘文件中,也就是将 Java 对象对象的状态保存下来存储到文件中的过程就叫做序列化。

将硬盘中保存了 Java 对象状态的字节序列按照编号组装成对象恢复到内存中,这个过程称为反序列化。

3 应用示例

参与序列化和反序列化的 Java 类

public class Student implements Serializable { private String name; private int age; // 以下省略有参构造、无参构造、set、get、toString} 参与序列化和反序列化的类必须实现 Serializable 接口。

序列化操作

public static void main(String[] args) throws Exception { // 创建 Java 对象 Student student = new Student("sddx",22); // 对象输出流 ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("student")); // 使用 writeObject 序列化对象 oos.writeObject(student); // 刷新 oos.flush(); // 关闭流 oos.close();} 序列化后的二进制文件会被保存到文件输出流指定的路径。

反序列化操作

public static void main(String[] args) throws Exception { // 对象输入流 ObjectInputStream ois = new ObjectInputStream(new FileInputStream("student")); // 使用 readObject() 反序列化 Object obj = ois.readObject(); // 使用对象 System.out.println(obj); // 关闭流 ois.close();} 反序列化需要借助文件输入流读取指定路径的二进制文件。 4 序列化版本号的作用 serialVersionUID

JVM 首先会通过类名来区分 Java 类,类名不同,则不是同一个类。当类名相同时,JVM 就会通过序列化版本号来区分 Java 类,如果序列化版本号相同就为同一个类,序列化版本号不同就为不同的类。

在序列化一个对象时,如果没有指定序列化版本号,后期对该类的源码进行修改并重新编译后,会导致修改前后的序列化版本号不一致,因为 JVM 会提供一个新的序列化版本号给该类对象。

此时再用以往的反序列化代码去反序列化该类的对象,就会抛出异常 java.io.InvalidClassException ,所以序列化一个类时最好指定一个序列化版本号,或者永远不修改此类。

public class Student implements Serializable { private static final Long serialVersionUID = 1L;}

由 JVM 提供序列化版本号的好处是,同名却不同功能的类,会有两个不同的序列化版本号,JVM 可以通过序列化版本号加以区分,缺点是一旦修改源码,会重新提供序列化版本号,导致修改前后的序列化版本号不一致,进行反序列化时会出现运行出现异常。

由 开发人员 手动提供序列化版本号的好处是,当修改了被序列化类的源码后,以往写的反序列化代码依然可以使用,如 JDK 中的 String 类。以便后期进行增强和维护不会影响使用。

5 transient 关键字

这个关键字表示游离的,不参与序列化的。

在序列化一个对象时,如果不希望某个属性参加序列化,可以使用 transient 修饰该属性。

被该关键字修饰的属性不会参与到序列化中。

public class Student implements Serializable { private static final Long serialVersionUID = 1L; private String name; private transient int age;} 如上类,在序列化时就不会保存 age 属性,在反序列化时就不能会付出该属性,默认恢复成 null 或 0 ,由属性类型决定。 6 序列化的好处及应用场景

序列化会将内存中对象的状态转换成二进制文件保存到磁盘当中,当再次使用时会从磁盘中读取该二进制文件,将 Java 对象的状态恢复到内存中。

xydlm想把内存中的对象保存到磁盘文件或数据库中时可以使用序列化。

xydlm想在网络传输中传送 Java 对象时,可以使用序列化。

xydlm想通过 RMI 传输对象时,可以使用序列化。

7 序列化注意事项

序列化只会保存对象的属性状态,不会保存对象中的方法。

父类实现了 Serializable 接口,则其子类也自动实例化了该接口,也就是说子类不用显式实现 Serializable 接口也能参与序列化和反序列化。

一个对象 A 的实例变量引用了其他对象 B,在 A 对象实例化的过程中 ,也会序列化 B ,前提是 A、B 两个类都实现了 Serializable 接口。

当一个类实现 Serializable 接口时,最好手动指定一个序列化版本号(serialVersionUID),避免修改源代码后导致反序列化出现异常。

当一个类对象会被多次重复使用,且一般不会对其属性做修改,就可以对其进行序列化。例如数据库操作中的实体类。

参考博文:

菜鸟教程

对Java Serializable(序列化)的理解和总结

java序列化,看这篇就够了

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。