序列化与反序列化

序列化是通过实现 java.io.Serializable 接口来实现的

序列化的作用

数据持久化:序列化可以将对象的状态转换为字节流,然后将这些字节流保存到文件或数据库中,实现数据的持久化存储。

网络传输:在网络通信中,序列化用于将对象转换为字节流,以便通过网络发送到其他计算机或设备,然后在接收端将字节流反序列化回对象。

分布式系统:在分布式系统中,序列化用于在不同的节点或服务之间传输对象状态,以实现数据的共享和同步。

跨语言交互:不同编程语言的系统可以通过序列化来交换数据。例如,一个Java对象可以被序列化,然后被Python程序反序列化。

序列化关键的接口和关键字

Serializable 接口:一个标记接口,用于指示一个类可以被序列化。实现此接口的类的对象可以被 ObjectOutputStream 类的实例写入,并可以通过 ObjectInputStream 类的实例读出。

ObjectOutputStream:用于将Java对象的原始数据类型写入到输出流中。这是序列化的核心类。

ObjectInputStream:用于从输入流中读取Java对象的原始数据类型。它是反序列化的核心类。

writeObjectreadObject 方法:这两个方法允许对象在序列化和反序列化过程中自定义其行为。它们可以是类的私有方法,并在类的内部调用。

transient 关键字:当成员变量声明为 transient,它就不会被序列化。这意味着这个变量的值在反序列化后不会被恢复。

serialVersionUID:类似于类的版本号,用于在反序列化过程中确保发送和接收的类的版本兼容。

   public static void main(String[] args) throws IOException {
       Person person = new Person("Tom", 32);
       FileOutputStream fileOutputStream = new FileOutputStream(new File("D:/person.txt"));
       ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
       objectOutputStream.writeObject(person);
       objectOutputStream.close();
       fileOutputStream.close();
       System.out.println("over");
   }

序列化的实现方式

类实现Serializable接口

Serializable接口是一个标记接口,不用实现任何方法。一旦实现了此接口,该类的对象就是可序列化的

类中属性的类型

如果一个可序列化的类的成员不是基本类型,也不是String类型,那这个引用类型也必须是可序列化的

自定义对象类型不可进行序列化,否则报错

对象的多次序列化

JVM是通过类名来区分Java类的,当具有相同的类名,JVM就会给类分配一个序列版本号来进行序列和反序列化的标识。

第一次序列化输出的是对象的序列化信息

接下来的就是输出JVM为该类分配的序列化版本号

第一种情况:没有指定序列版本号,JVM会自动为该序列对象分配一个序列版本号,若修改了类的信息,JVM会重新分配一个序列版本号,此时我们再用以往的反序列化代码进行反序列化就会报错

 第二种情况:制定了版本序列号,JVM在进行序列和反序列化时,把版本序列号作为唯一标识,当你对类进行修改了,JVM会使用默认值,基本数据类型时‘0’,引用数据类型是'null',boolean类型默认是false

小技巧

父类实现了Serializable接口,子类自然隐式的实现类Serializable接口。

当一个类的属性基本不会进行更改,就可以对该类进行序列化,比如说项目中的实体类

当该类指定了序列化版本号(serialVersionUID),后续对该类更改属性了,依旧可以进行序列化和反序列化

总结

  1. 所有需要网络传输的对象都需要实现序列化接口,通过建议所有的javaBean都实现Serializable接口。
  2. 对象的类名、实例变量(包括基本类型,数组,对其他对象的引用)都会被序列化;方法、类变量、transient实例变量都不会被序列化。
  3. 如果想让某个变量不被序列化,使用transient修饰。
  4. 序列化对象的引用类型成员变量,也必须是可序列化的,否则,会报错。
  5. 反序列化时必须有序列化对象的class文件。
  6. 当通过文件、网络来读取序列化后的对象时,必须按照实际写入的顺序读取。
  7. 单例类序列化,需要重写readResolve()方法;否则会破坏单例原则。
  8. 同一对象序列化多次,只有第一次序列化为二进制流,以后都只是保存序列化编号,不会重复序列化。
  9. 建议所有可序列化的类加上serialVersionUID 版本号,方便项目升级。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值