对象序列化
对象序列化将 Java 对象转换为字节流,实现持久化存储和网络传输。
Serializable 接口
基本用法
Java
public class User implements Serializable {
private String name;
private int age;
// 序列化版本号(推荐显式定义)
private static final long serialVersionUID = 1L;
// transient 标记不序列化的字段
private transient String password;
public User(String name, int age) {
this.name = name;
this.age = age;
}
}
serialVersionUID:版本控制,反序列化时版本号不一致抛 InvalidClassException。建议显式定义避免类修改后反序列化失败。
ObjectOutputStream 序列化
Java
User user = new User("张三", 25);
try (ObjectOutputStream oos = new ObjectOutputStream(
new FileOutputStream("user.dat"))) {
oos.writeObject(user); // 序列化对象
}
ObjectInputStream 反序列化
Java
try (ObjectInputStream ois = new ObjectInputStream(
new FileInputStream("user.dat"))) {
User user = (User) ois.readObject(); // 反序列化
System.out.println(user.getName());
}
transient 关键字
标记字段不参与序列化:
Java
public class User implements Serializable {
private String name;
private transient String password; // 不序列化
// 反序列化后 password 为 null
}
适用场景:
- 密码、密钥等敏感信息
- 临时状态、缓存数据
- 不可序列化的对象引用
序列化规则
| 规则 | 说明 |
|---|---|
| 必须实现 Serializable | 否则抛 NotSerializableException |
| static 不序列化 | 静态成员属于类,不随对象序列化 |
| transient 不序列化 | 标记字段跳过序列化 |
| 引用对象必须可序列化 | 成员对象也需实现 Serializable |
| 父类序列化规则 | 父类未实现 Serializable 则其字段不序列化 |
序列化注意事项
循环引用问题
Java
public class Node implements Serializable {
Node next; // 引用自己,序列化会处理循环引用
}
// 序列化自动处理,但可能导致栈溢出(深度过大)
单例序列化问题
Java
public class Singleton implements Serializable {
private static final Singleton INSTANCE = new Singleton();
// 反序列化会创建新对象,破坏单例
// 解决:实现 readResolve() 返回单例实例
private Object readResolve() {
return INSTANCE;
}
}
要点总结
- 实现 Serializable 接口才能序列化
- serialVersionUID 控制版本兼容,建议显式定义
- transient 标记字段不序列化
- static 字段不序列化(属于类)
- ObjectOutputStream.writeObject() 序列化
- ObjectInputStream.readObject() 反序列化
- 单例反序列化需实现 readResolve() 保持单例
📝 发现内容有误?点击此处直接编辑