引用类型在序列化中需将内存地址抽象转为状态数据,因其本质是堆中对象引用,网络仅支持字节传输;java/c#要求显式标记(如serializable接口或[serializable]特性),并处理循环引用、泛型约束及类版本兼容性,避免反序列化失败。

引用类型在网络传输中不能直接发送,必须先序列化为可传输格式;接收方收到后,再反序列化还原为可用的对象实例。
什么是引用类型在序列化中的特殊性
Java、C# 等语言中的引用类型(如 User、List
关键点在于:序列化不是复制引用,而是复制状态;反序列化不是恢复地址,而是新建对象并填充相同状态。
常见引用类型的序列化处理方式
不同引用类型在序列化时行为有差异,需注意:
-
普通 POJO 类:需实现
Serializable接口(Java)或标记[Serializable](C#),否则抛出异常;字段默认全量序列化,transient或[NonSerialized]修饰的字段被跳过。 -
集合类(List/Map/Set):本身可序列化,但要求其泛型元素类型也支持序列化;例如
List<user></user>能序列化,前提是User可序列化。 -
含循环引用的对象图:如 A 引用 B,B 又引用 A。Java 原生序列化能识别重复引用并写入“引用标记”,避免无限递归;JSON/XML 默认不支持,需额外配置(如 Jackson 的
@JsonIdentityInfo)。 -
接口或抽象类实例:序列化时保存的是实际运行时类型(如
Map接口变量存的是HashMap实例),反序列化需能重建该具体类型,否则失败。
网络传输中必须关注的兼容性问题
引用类型跨进程、跨语言传输时,结构一致性比基本类型更敏感:
- 类名、包路径、字段名必须严格匹配(Java 原生序列化依赖
serialVersionUID校验;不一致会抛InvalidClassException)。 - 字段增删改需考虑版本兼容策略:加字段设默认值、删字段加
transient、改类型需自定义readObject/writeObject方法。 - 优先选用语言中立格式(如 JSON、Protocol Buffers),避免 Java 原生
.ser文件这类强绑定格式——它无法被 Python 或 Go 直接反序列化。 - 时间类型、枚举、BigDecimal 等非基础类型,在不同序列化器中表现不一(如 Jackson 把
LocalDateTime默认转为字符串,Gson 可能报错),需统一约定格式。
实际传输建议
面向生产环境的网络传输,不推荐直接用 Java 原生序列化:
- 安全风险高:反序列化任意字节流可能触发远程代码执行(如 Apache Commons Collections 漏洞)。
- 性能较差:二进制体积大、解析慢、无向后兼容设计。
- 推荐组合:JSON + 显式 DTO 类(非业务实体),配合 Jackson/Gson;高频低延迟场景用 Protobuf,定义 .proto 后生成强类型类,兼顾效率与跨语言能力。
- 务必校验反序列化结果:检查关键字段是否为 null、集合是否为空、枚举值是否在预期范围内,防止因数据污染导致运行时异常。











