注解不参与序列化,因其属于编译期/运行期元数据,不存储在对象实例中;仅字段值、类型及引用关系被序列化。框架注解(如@jsonignore)通过反射影响序列化行为,但本身不进入字节流。

Java 中的注解在序列化或网络传输时默认不会被保留,因为注解本身不是对象状态的一部分,它属于编译期或运行期的元数据,而序列化只保存对象的字段值、类型信息和引用关系。
为什么注解不参与序列化
序列化机制(如 ObjectOutputStream)关注的是对象的运行时状态:即非 transient、非 static 的字段值及其类型。注解是附加在类、字段、方法上的元数据,存储在 class 文件的 RuntimeVisibleAnnotations 等属性中,并不随对象实例一起存入堆内存,更不会被写入字节流。
换句话说:序列化操作处理的是“值”,而注解描述的是“结构或语义”,二者处在不同抽象层级。
哪些注解可能间接影响序列化行为
虽然注解本身不被序列化,但某些框架级注解会通过反射在序列化过程中起作用:
-
@JsonIgnore(Jackson):让字段在 JSON 序列化时被忽略 -
@JsonInclude(JsonInclude.Include.NON_NULL):控制 null 字段是否输出 -
@Transient(JPA):仅影响数据库映射,与 Java 原生序列化无关;但名字易混淆,注意它和transient关键字无直接关系 -
@SerializedName(Gson):指定字段在 JSON 中的名称,反序列化时用于匹配键名
这类注解生效的前提是使用了对应框架(如 Jackson/Gson)做序列化,而不是 JDK 原生的 ObjectOutputStream。它们在运行时通过反射读取,再动态决定如何处理字段,但注解内容本身仍不会出现在最终的字节流或 JSON 字符串里。
能否让注解也“跟着对象走”
不能直接做到。如果真有需求把注解信息持久化或传输,需手动实现:
- 在序列化前,用反射提取关键注解值,存入一个额外字段(如
Map<string object> metadata</string>) - 自定义
writeObject/readObject方法,在其中显式读写注解相关内容 - 改用支持元数据导出的序列化方案(如 Protobuf + 自定义 option,或 Avro schema),但这已超出 Java 原生序列化范畴
本质上,这是设计权衡:保持序列化轻量、高效,不捆绑结构描述信息。
所以结论很明确:注解是开发阶段的“说明书”,序列化是运行时的“快照”,说明书不会自动装进快照里。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











