1. Java 序列化简介
序列化是从一个对象(Object)转化为一个字节流(byte stream)的过程。而反序列化恰恰相反,是在内存中使用字节流构建一个确切的 Java 对象的过程。
2. 序列化与反序列化
Java 序列化的过程是与平台无关的(platform-independent),也就是说一个 Java 对象可以在一个平台上序列化之后传输到另外一个平台上进行反序列化。需要进行序列化的 Java 类必须实现一个特殊的标记接口(maker interface)——Serializable。只有实现了 java.io.Serializable 接口的类可以进行序列化/反序列化,其中java.io.Serializable 接口是一个标记接口(maker interface),标记接口不含有任何成员和方法,标记接口的作用是标记一组类,这些类都具有相同的特定的功能,常见的标记接口还有 Cloneable。
对于常见的两个类:ObjectInputStream 和 ObjectOutputStream ,分别是 java.io.InputStream 和 java.io.OutputStream 这两个类的高级延伸。ObjectInputStream 类可以将更原始的类型以字节流的形式写入到 OutputStream 中。ObjectInputStream 中最重要的方法是:
public final void writeObject(Object o)
throws IOException;
这个方法的作用是:接收一个可序列化的对象 o ,将 o 转换成一个连续的字节流。
同样的在 ObjectInputStream 类中最重要的方法是:
public final Object readObject()
throws IOException, ClassNotFoundException;
这个方法的作用是:接收一端字节流,将字节流转化为一个 Java 对象,也就是转化回溯到最初的对象。
使用序列化带来的好处
- 保存一个对象的状态
- 可以通过网络传输对象
3. Java 序列化的几个特点
类的继承与组成
如果父类实现了 Serializable 接口,那么其子类不用显式的说明也自动的实现了此接口。但反过来不成立。并且这个类引用的对象(例如内部类、作为成员变量的类等)也必须实现 Serializable 接口。例如:
public class Person implements Serializable {
private int age;
private String name;
private Address country; // must be serializable too
People people = new People();
}
由于上面的代码中的可序列化的类 Person 引用了 Address 类与 People 类,所以这两个类也必须在定义的时候实现 Serializable 接口,否则会抛出 NotSerializableException 异常。
序列化过程中的数据保存
在序列化的过程中只有非静态成员的数据会被保存,静态成员的数据和 transient 成员的数据在序列化过程中不会被保存。所以如果你不想保存费静态成员的数据,只需要将其使用 transient 修饰即可。
下面我们构造一个 Person 类来对序列化和反序列化过程有一个直观的认识。下面构造一个 Person 类,其中含有静态变量 country ,非静态变量 age 、name 以及 transient 变量 height。
public