一、Java序列化概述
1、什么是序列化
序列化(Serialization):是将对象的状态信息转换为可以存储或传输的形式的过程。更通俗地讲,是将该对象字段和状态信息以字节流的方式输出到目的地。
2、序列化的应用场景
- 一是实现pojo对象的读写操作,将每个对象转换为字节流,而这些字节流可以被持久化到设备上,再次读取时会将字节流还原成对象。当我们希望某些数据能在程序停止运行后,还能继续存在。在程序再次执行时还能获取这些数据时,或者让其他的程序也能够利用这些数据资源时。这就是我理解的应用场景一。
- 二是实现网络间的数据传输。网络间的数据传输是高频发而且数据量也是非常大的。以订单数据传输为例,当我们希望获取到订单类里的全部数据并据此生成一份订单的excel文件时,这个订单类就必须要实现序列化,这是我理解的应用场景二。
3、Java序列化的方式
Java序列化提供两种方式。
- 一种是实现Serializable接口
使用该方式非常简单,通过重写该接口预置的5个方法,可以达到对序列化的控制。不重写这些方法,也可以自动序列化,非常方便。 - 另一种是实现Externalizable接口。
不像Serializable接口只是一个标记接口,Externalizable接口强制你自己动手实现串行化和反串行化方法。它的效率比Serializable高一些,并且可以决定哪些属性需要序列化(即使是transient修饰的),但是要求必须重写两个方法。Externalizable对小数目对象有效的多。但是对大量对象,或者重复对象,则效率低。
4、Java序列化的特点
java对象序列化不仅保留一个对象的数据,而且递归保存对象引用的每个对象的数据。可以将整个对象层次写入字节流中,可以保存在文件中或在网络连接上传递。利用对象序列化可以进行对象的”深复制”,即复制对象本身及引用的对象本身。序列化一个对象可能得到整个对象序列。
二、Java序列化方式
Serializable接口
java.io.Serializable的源码注释大概分为以下几个点
- java.io.Serializable是一个空接口:
public interface Serializable {
}
源码注释中说到:
* Serializability of a class is enabled by the class implementing the
* java.io.Serializable interface. Classes that do not implement this
* interface will not have any of their state serialized or
* deserialized.
大意是说,只有实现该接口的类,才能序列化和反序列化(注意,Externalizable也继承了该接口)。
- 为了允许非序列化类的子类型进行序列化(例如,子类实现了Serializable接口,但是父类并没有实现),子类型需要承担父类的public、protected和package访问权限字段的存储和恢复任务。因此,需要父类提供一个无参的构造器,以便子类进行状态的初始化。
- 在反序列化期间,非序列化类的字段将会被public或者protected类型的无参构造器初始化。父类的构造器必须要能够被可序列化的子类所访问。可序列化子类的字段将会被流恢复。
- 当遍历一个图,可能会遇到一个不支持序列化接口的对象。在这种情况下,将会抛出NotSerializableException并标志该类为不可序列化。
- 一些在序列化或者反序列化期间需要做一些特别操作的类,必须实现下面这些完整签名的方法:
private void writeObject(java.io.ObjectOutputStream out) throws IOException
private void readObject(java.io.ObjectInputStream in)
throws IOException, ClassNotFoundException;
private void readObjectNoData() throws ObjectStreamException;
- writeObject()方法用于将对象的当前状态写入到一个对象输出流中,并由输出流决定余下的操作(如,是输出到本地文件还是网络中)
- readObject()负责从指定对象输入流中读出并恢复类的字段。该