java对象序列化引用类型时,会递归序列化整个对象图,要求所有引用类实现serializable,否则抛notserializableexception;transient字段跳过序列化;支持循环引用但需防膨胀;所有相关类须实现接口并声明serialversionuid。

Java 对象序列化保存引用类型到磁盘,核心在于整个对象图的递归序列化——不是只存引用地址,而是把被引用的对象也一并序列化进去,形成一个连贯的、可重建的结构。
只要被引用的对象类也实现了 Serializable,它就会被自动写入字节流;否则会抛出 NotSerializableException。
引用类型必须可序列化
-
ObjectOutputStream在写入包含引用字段的对象时,会检查该引用指向的对象所属类是否实现了Serializable。 - 如果没实现,运行时报错,例如:
class Person implements Serializable { private String name; private User user; // User 必须也实现 Serializable } - 若
User没实现接口,哪怕Person实现了,也会失败。
transient 字段跳过序列化
- 用
transient修饰的引用字段(如transient DatabaseConnection conn)不会被序列化,反序列化后值为null。 - 这适用于不能或不该持久化的资源(连接、线程、IO 流等)。
- 如需自定义处理,可配合
writeObject()/readObject()方法手动写入/恢复。
父类引用与继承关系
- 如果引用类型是父类(比如
Animal pet = new Dog()),只要Dog实现了Serializable,就能正常序列化。 - 但若
Animal是抽象类且未实现Serializable,而Dog实现了,没问题;
反之,如果Animal实现了但Dog没有,也会失败——子类必须显式支持序列化。
避免循环引用问题
- Java 序列化能处理对象间的循环引用(如 A 引用 B,B 又引用 A),内部通过对象句柄机制避免重复写入。
- 但要注意:若引用链过深或存在大量冗余对象,可能造成文件体积膨胀或栈溢出。
- 可用
oos.reset()清除已写对象缓存(适合复用流写多个独立对象),但不解决设计层面的循环依赖问题。
实际写法要点
- 所有参与序列化的类(包括字段类型、集合元素类型)都应实现
Serializable。 - 显式声明
serialVersionUID,防止因类结构变动导致反序列化失败。 - 使用 try-with-resources 确保流正确关闭,避免
StreamCorruptedException。 - 不要对
ObjectOutputStream多次调用writeObject()写多个对象而不重置——推荐打包成List一次性写入,或每次新建流。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











