一、什么是Java序列化?
Java序列化(Serialization)是指把Java对象转化为字节序列,以便用于网络传输、文件保存或其他方式的持久化存储。反序列化则是将字节序列恢复成原有的Java对象的过程。
简单来说,序列化是“把对象拍成一张快照存下来”,以后需要的时候“把快照恢复成对象”。
二、Java序列化的实际应用场景
- 远程通信(RMI、RPC等):将对象在网络上传输到另一台机器上重建。
- 持久化存储:对象写入磁盘、数据库等介质,进行数据持久化。
- 分布式计算:如分布式缓存(Redis)、消息中间件(Kafka)等,经常需要序列化和反序列化对象。
- 深拷贝:通过序列化和反序列化实现对象的深度克隆。
三、Java序列化的基础知识
1. 如何实现序列化
想让一个Java对象能被序列化,主要有两种方式:
(1)实现Serializable接口
这是最常见的方式,只需要让类实现java.io.Serializable接口即可。比如:
public class Person implements Serializable {
private String name;
private int age;
}
注意:Serializable接口是个“标记接口”,没有任何方法。
(2)实现Externalizable接口
Externalizable接口需要手动实现writeExternal和readExternal方法,完全自定义“如何写、如何读”。
2. 序列化注意事项
- 序列化操作常用的流是
ObjectOutputStream和ObjectInputStream。 - 如果字段不想参与序列化,使用
transient关键字修饰。 - 父类没有实现Serializable,子类也不能序列化父类的字段。
- 推荐为每个serializable类都加
serialVersionUID,避免版本不一致导致反序列化失败。
四、Java序列化的底层机制简析
-
序列化过程
JVM 会将对象结构、字段类型及数据编码为字节流,记录类名、字段名、类型签名等元数据。 -
反序列化过程
JVM 利用类名和serialVersionUID匹配类定义,再用字节数据恢复对象并赋值字段。 -
serialVersionUID
类的序列化版本号,序列化和反序列化时必须一致,否则报InvalidClassException。
五、序列化的常见坑与最佳实践
1. 序列化性能较低
Java原生序列化的字节流较大,效率不高,兼容性一般。实际工作中,往往会选择以下高性能序列化框架:
- Hessian
- Kryo
- Protobuf
- Fastjson(JSON编码)
2. 类结构变动导致的兼容性问题
- 字段增删、类型更改会影响反序列化。
- 建议明确管理serialVersionUID,兼容多版本对象。
3. 序列化安全
- 反序列化时如果数据来源不可信,容易引发“反序列化漏洞”。
- 建议只信任可信源数据,或用白名单(如ObjectInputStream的resolveClass方法)。
六、实际案例
1. 基本对象序列化与反序列化代码示例
// 序列化
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("person.ser"));
oos.writeObject(new Person("张三", 18));
oos.close();
// 反序列化
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("person.ser"));
Person p = (Person) ois.readObject();
ois.close();
2. transient的使用
class User implements Serializable {
private String username;
private transient String password; // 不参与序列化
}
七、总结
Java序列化是Java对象持久化和分布式应用通信的基础能力,虽然操作简单,但处理大数据量、复杂对象、长生命周期或跨版本时,需要关注性能、兼容性及安全性。推荐日常开发选择更现代的序列化框架如Kryo、Protobuf等,并加强反序列化安全校验。
1376

被折叠的 条评论
为什么被折叠?



