首页 > 编程笔记 > Java笔记 阅读:9

Java序列化和反序列化(附带实例)

为了在 Java 程序中能直接把 Java 对象保存起来,然后重新得到该 Java 对象,需要用到 Java 的序列化和反序列化能力。

序列化可以看成一种机制,即按照一定的格式将 Java 对象转换成介质可接受的形式,以方便存储或传输,反过来则称为反序列化:
序列化和反序列化的含义如下图所示:


图 1 序列化与反序列化过程

在 Java 中进行序列化与反序列化操作时,需要实现 Serializable 接口。序列化和反序列化的过程都可能涉及对其他对象的引用,所以所引用的对象的相关信息也要参与序列化和反序列化。

总结起来,序列化是将 Java 对象相关的类信息、属性及属性值等以一定的格式转换为字节流,而反序列化则是根据字节流所表示的信息来构建出 Java 对象。

序列化与反序列化的主要作用包括下面 4 点:
  1. 提供一种简单且可扩展的对象保存与恢复机制;
  2. 对于远程调用来说,它能方便地对对象进行编码和解码,看起来就像是直接传输对象;
  3. 可以将对象持久化到存储介质中,看起来就像是直接存储对象;
  4. 允许对象自定义外部存储的格式。

序列化常见的使用方式是直接将对象写入流中,例如:
public class SerializationTest {
    public static void main(String[] args) throws IOException {
        FileOutputStream fos = null;
        ObjectOutputStream oos = null;
        try {
            A a = new A();
            a.name = "seaboat";
            a.age = 20;
            fos = new FileOutputStream("D:/tmp.o");
            oos = new ObjectOutputStream(fos);
            oos.writeObject("test");
            oos.writeObject(a);
            oos.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            oos.close();
            fos.close();
        }
    }
}

class A implements Serializable {
    String name;
    int age;
}
程序中首先创建了 FileOutputStream 对象,指定将对象信息输出并保存到“D:/tmp.o”文件中,然后创建 ObjectOutputStream 对象封装前面的输出流,最后调用 writeObject() 方法即能实现序列化操作。

对于 writeObject() 方法需要特别说明一下,当对某个对象进行写入时,其实不仅是序列化该对象,还会遍历寻找相关引用的其他对象,由该对象和其他引用对象组成的完整的对象图关系都会被序列化。参与序列化的类必须实现 Serializable 或 Externalizable 接口才能被序列化。

反序列化是序列化的反向操作,即通过字节流来还原 Java 对象。例如:
public class SerializationTest2 {
    public static void main(String[] args) throws IOException {
        FileInputStream ins = null;
        ObjectInputStream ois = null;
        try {
            ins = new FileInputStream("D:/tmp.o");
            ois = new ObjectInputStream(ins);
            String str = (String) ois.readObject();
            A a = (A) ois.readObject();
            System.out.println(str);
            System.out.println(a.name + " " + a.age);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            ins.close();
            ois.close();
        }
    }
}
程序中首先创建 FileInputStream 对象,指定输入的文件为“D:/tmp.o”。然后创建 ObjectInputStream 对象封装前面的输入流,接着调用 readObject() 方法读取对象。readObject() 方法除了会恢复对象自身,还会遍历整个完整的对象图关系,以创建整个对象图包含的所有对象。

注意,反序列化时读取对象的顺序必须与序列化时写入对象的顺序保持一致。

相关文章