一、序列化与反序列化
序列化(Serialize):把对象转换为字节序列存储于磁盘或者进行网络传输的过程称为对象的序列化(对象->流数据) 。Java提供了一种对象序列化的机制,该机制中,一个对象可以被表示为一个字节序列,该字节序列包括该对象的数据、有关对象的类型的信息和存储在对象中数据的类型。序列化也可以理解为拆分对象,是指将对象的状态信息转换为可以存储或传输的形式(二进制数据)的过程,在序列化期间,对象将其当前状态写入到临时或持久性存储区,以后可以通过从存储区中读取或反序列化对象的状态,重新创建该对象
序列化的目的: 永久的保存对象,保存对象的字节序列到本地文件中(在MVC模式中很有用) 通过序列化对象在网络中传递对象 通过序列化对象在进程间传递对象
反序列化(DeSerialize):把磁盘或网络节点上的字节序列恢复到对象的过程称为对象的反序列化(流数据->对象) 。将序列化对象写入文件之后,可以从文件中读取出来,并且对它进行反序列化,也就是说,对象的类型信息、对象的数据,还有对象中的数据类型可以用来在内存中新建对象。反序列化也可以理解为组装对象,是指将硬盘上的数据重新恢复到内存当中,恢复成Java对象
网络传输:序列化与反序列化实现了进程通信间的对象传送 ,发送方需要把这个Java对象转换为字节序列,才能在网络上传送;接收方则需要把字节序列再恢复为Java对象,所以实现了远程通信,即在网络上传递对象的字节序列
整个过程都是 Java 虚拟机(JVM)独立的,也就是说,在一个平台上序列化的对象可以在另一个完全不同的平台上反序列化该对象
二、ObjectOutputStream(序列化对象流)
Java是一种完全面向对象的高级语言,所以在编写程序的时候数据大都存放在对象当中,有时会需要将内存中的整个对象都写入到文件中去,此时可以使用java.io.ObjectOutputStream类来完成此需求,此操作被称为序列化
序列化步骤
创建一个FileOutputStream对象(ObjectOutputStream的构造方法中需要传入一个OutputStream)
FileOutputStream fos = new FileOutputStream ( "" ) ;
创建序列化对象
ObjectOutputStream oos = new ObjectOutputStream ( fos) ;
序列化,写
oos. writeObject ( ) ;
刷新
oos. flush ( ) ;
关闭
oos. close ( ) ;
三、ObjectInputStream(反序列化对象流)
Java是一种完全面向对象的高级语言,所以在编写程序的时候数据大都存放在对象当中,有时会需要将内存中的整个对象都写入到文件中去,然后在适当的时候再从文件中将对象还原至内存,还原的时候可以使用java.io.ObjectInputStream类来完成,此操作被称为反序列化
反序列化步骤
创建一个FileInputStream对象(ObjectInputStream的构造方法中需要传入一个InputStream)
FileInputStream fis = new FileInputStream ( "" ) ;
创建反序列化对象
ObjectInputStream ois = new ObjectInputStream ( fis) ;
反序列化,读
Object readObject = ois. readObject ( ) ;
关闭
ois. close ( ) ;
四、Serializable接口
参与序列化和反序列化的对象,必须实现Serializable接口,如果没有实现序列化接口,则会抛出NotSerializableException异常
序列化多个对象时,使用序列化集合,另外参与序列化的集合以及集合中的元素都需要实现java.io.Serializable接口
Serializable接口只是一个标志接口
public interface Serializable {
}
Serializable接口的作用 标志的作用,Serializable这个标志接口是给JVM参考的,如果没有手动设置序列化版本号,JVM看到这个接口之后,会为该类自动生成一个序列化版本号(不建议自动生成)
序列化版本号
Java中采用什么机制区分类: 先进行类名的比较,如果类名一样,则通过版本号进行区分
java.io.InvalidClassException异常 local class incompatible: stream classdesc serialVersionUID = 5469762016150375948, (修改后) local class serialVersionUID = 8677421558351689747(修改前) 即如果是自动生成序列化版本号,在修改源代码的时候,必然会修改序列化版本号,在进行反序列化的时候,无法找到修改之前的序列化版本号,即序列化版本号不一致,最终导致InvalidClassException异常发生
自动生成序列化版本号的劣势 源代码确定之后,不能进行后续的修改,因为只要修改,必然会重新编译,那么就会生成新的序列化版本号,此时JVM会认为这是一个新的类
凡是一个类实现了Serializable接口,建议给该类提供一个固定不变的序列化版本号,以后即使此类的源代码修改,但序列化版本号不变,JVM会认为是同一个类
五、测试用例
1. 序列化单个对象
import java. io. Serializable;
public class Student implements Serializable {
private static final long serialVersionUID = - 4760929539457435312 L;
private int no;
private String name;
public Student ( ) {
}
public Student ( int no, String name) {
th