Java 序列化
概述
Java 序列化是一种机制,允许将 Java 对象的状态转换为字节流,以便可以将其保存到文件或通过网络发送。这个过程称为序列化。反序列化是序列化的逆过程,它将字节流转换回 Java 对象。序列化在 Java 中是非常重要的,因为它支持多种关键功能,如远程方法调用(RPC)、JavaBeans 和持久化。
序列化的基本概念
对象图
序列化过程不仅仅是对单个对象的状态进行编码,而是对整个对象图进行编码。这意味着如果一个对象引用了其他对象,那么这些被引用的对象也会被序列化。
可序列化
要使对象可序列化,它的类必须实现 java.io.Serializable
接口。这个接口是一个标记接口,没有方法需要实现,但它告诉 Java 序列化框架该类的对象可以被序列化。
serialVersionUID
serialVersionUID
是一个唯一标识符,用于在序列化和反序列化过程中验证类的版本。如果类的定义在序列化后发生了变化,那么反序列化时可能会失败,除非 serialVersionUID
保持不变。
序列化过程
序列化过程涉及以下几个步骤:
- 创建一个
ObjectOutputStream
。 - 调用
writeObject
方法,将对象写入流中。 - 处理对象的字节数据。
反序列化过程
反序列化过程与序列化过程相反,涉及以下几个步骤:
- 创建一个
ObjectInputStream
。 - 调用
readObject
方法,从流中读取对象。 - 恢复对象的字节数据。
注意事项
- 静态变量不会被序列化,因为它们属于类,而不是对象。
- transient 关键字可以用于标记不想被序列化的字段。
- 确保对象图中的所有对象都是可序列化的,否则序列化过程会抛出
NotSerializableException
。
示例
以下是一个简单的序列化和反序列化示例:
import java.io.*;
public class SerializationDemo {
public static void main(String[] args) {
// 序列化
try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("object.ser"))) {
Student student = new Student("John Doe", 20);
out.writeObject(student);
} catch (IOException e) {
e.printStackTrace();
}
// 反序列化
try (ObjectInputStream in = new ObjectInputStream(new FileInputStream("object.ser"))) {
Student student = (Student) in.readObject();
System.out.println(student.getName() + " " + student.getAge());
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
}
class Student implements Serializable {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
在这个示例中,我们创建了一个 Student
类,实现了 Serializable
接口。然后,我们创建了一个 Student
对象,并将其序列化到文件中。接着,我们反序列化该对象并打印其信息。
结论
Java 序列化是一个强大的特性,它允许 Java 程序员轻松地保存和传输对象。然而,它也有一些限制和需要注意的地方,如对象图的处理、serialVersionUID
的管理以及 transient 字段的处理。正确使用序列化可以大大简化 Java 程序的开发和维护。