java多态与序列化可协同工作:原生序列化自动保留运行时类型,反序列化后仍保持子类行为;json需jackson等通过@jsontypeinfo等注解显式声明多态策略,否则丢失子类特性。

Java多态机制与序列化不是互斥的两个特性,而是可以协同工作的关键能力。只要类型信息在序列化过程中被正确保留,反序列化后仍能维持动态绑定行为——子类对象不会“退化”为父类空壳。
序列化天然支持运行时多态
Java原生序列化(基于Serializable)默认记录对象的实际运行时类型,而非引用声明类型。这意味着:
- 用
Animal a = new Dog()序列化,保存的是Dog的完整类信息,包括字段值和类标识 - 反序列化得到的对象仍是
Dog实例,调用a.makeSound()会执行Dog重写的版本 - 无需额外注解或配置,只要父类和所有子类都实现
Serializable即可
JSON场景需显式声明多态策略
与二进制序列化不同,JSON是结构无关的文本格式,无法自动推断类型。Jackson等库必须借助注解注入类型元数据:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
-
@JsonTypeInfo(use = NAME, property = "type"):在JSON中添加"type": "dog"字段 -
@JsonSubTypes:将名称映射到具体类,确保反序列化时能构造出Dog而非Animal - 若省略这些注解,Jackson默认只按字段名匹配,反序列化结果是父类实例,丢失子类行为
关键限制与风险点
多态+序列化的组合并非无条件可靠,以下情况会导致行为异常:
- 子类新增了
transient字段:该字段值不会被序列化,反序列化后为默认值(如null或0) - 父类未实现
Serializable:整个继承链中断,抛出NotSerializableException - Jackson使用
CLASS策略但类路径变更:反序列化失败,因找不到原全限定类名 - 未注册子类型却启用
DefaultTyping:Jackson 2.16起默认拒绝未白名单类型,防止反序列化攻击
实际编码建议
为保障多态性在序列化中稳定生效,推荐做法:
- 所有参与多态的类统一实现
Serializable,并显式定义serialVersionUID - JSON场景优先选用
NAME策略而非CLASS,用业务语义名(如"user")替代类名 - 避免在子类中覆盖父类
readObject/writeObject方法却不调用super,否则破坏类型信息写入 - 对不可信JSON输入,始终配合
TypeValidator或@JsonSubTypes白名单控制反序列化范围
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










