在 Java 中,序列化(Serialization)是将对象的状态转换为可以保存或传输的格式的过程,然后可以通过反序列化(Deserialization)将这种格式恢复为对象。序列化在多种场景中非常有用,比如将对象保存到文件系统中、通过网络发送对象等。
序列化的主要点:
- 持久化对象状态:序列化使得对象的状态可以被持久保存到磁盘或其他存储媒介上,因此具有持久化数据的能力。
- 跨时空的对象传输:序列化使得可以通过网络等方式,在不同的时间和空间上共享对象。这在分布式系统中非常有用,可以用于远程方法调用(RMI)、消息传递等。
实现序列化:
要让 Java 对象可序列化,需要实现 java.io.Serializable
接口。这个接口是一个标记接口(Marker Interface),没有方法需要实现,它的作用是允许对象的类型在运行时表明自己支持序列化。
import java.io.Serializable;
public class User implements Serializable {
private static final long serialVersionUID = 1L; // 序列化版本号
private String name;
private transient int age; // transient 关键字表示临时的,不参与序列化过程
// 构造方法、Getter和Setter
}
序列化与反序列化的过程:
序列化过程:
使用 ObjectOutputStream
类将对象写入到输出流(比如文件输出流 FileOutputStream
)。
User user = new User();
user.setName("John Doe");
user.setAge(30);
try (FileOutputStream fos = new FileOutputStream("user.ser");
ObjectOutputStream oos = new ObjectOutputStream(fos)) {
oos.writeObject(user);
} catch (IOException e) {
e.printStackTrace();
}
反序列化过程:
使用 ObjectInputStream
类从输入流(比如文件输入流 FileInputStream
)读取并重构对象。
User user = null;
try (FileInputStream fis = new FileInputStream("user.ser");
ObjectInputStream ois = new ObjectInputStream(fis)) {
user = (User) ois.readObject();
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
if (user != null) {
System.out.println("User name: " + user.getName());
// 因为age是transient,所以它不会被序列化和恢复
System.out.println("User age: " + user.getAge());
}
注意事项:
- 使用
transient
关键字修饰的字段不会被序列化。 - 序列化操作不会自动序列化对象图中的静态成员。
- 修改序列化类定义(如添加方法或字段)后,可能需要更改
serialVersionUID
,否则反序列化过程可能会失败,抛出InvalidClassException
。 - 保密数据(如密码、PIN 码)不应序列化存储,以防止安全漏洞。
序列化和反序列化是 Java 中非常强大的特性,可用于多种场景,包括但不限于持久化、深度复制、对象交换等。