java反射不直接序列化,而是为gson/jackson等框架提供运行时解析类结构的能力:通过getdeclaredfields()、setaccessible()、get()/set()等操作动态读写字段,支撑未知类型(如class clazz)的序列化与反序列化全流程。

Java 中反射机制本身不直接做序列化与反序列化,而是为 Gson、Jackson 等框架提供“看懂类结构”的能力,从而让这些框架能处理未知类型对象(即编译期不确定、运行时才拿到 Class 的对象)。关键在于:反射是底层支撑,不是替代方案。
为什么需要反射来处理未知类型?
当你只有 Object obj 或一个 Class> clazz,却不知道它具体是 User、Order 还是 List<product></product> 时:
- 编译器无法生成字段访问代码
- 没有硬编码的 setter/getter 可调用
- 字段名、类型、是否忽略、如何格式化——全靠运行时查
反射正是解决这个问题的唯一通用手段。
反射如何支撑未知类型的序列化
以 Jackson 为例,调用 mapper.writeValueAsString(obj) 时:
- 通过
obj.getClass()获取Class对象 - 调用
clazz.getDeclaredFields()扫描所有字段(含 private) - 对每个字段:
-
field.setAccessible(true)打开私有访问 -
field.get(obj)读取值 - 根据字段类型(如
LocalDateTime)匹配内置或自定义 Serializer
-
- 字段名若被
@JsonProperty("user_name")修饰,就用注解值而非原始名
Gson 同理,只是用 FieldNamingPolicy 做字段名映射,底层仍是 getDeclaredFields() + get()。
反射如何支撑未知类型的反序列化
当执行 mapper.readValue(json, clazz)(注意第二个参数是 Class<t></t>):
- 框架用该
clazz创建实例:- 尝试无参构造器:
clazz.getDeclaredConstructor().newInstance() - 若有
@JsonCreator,则找对应构造器或静态工厂方法
- 尝试无参构造器:
- 解析 JSON 中的 key(如
"email"),用clazz.getDeclaredField("email")定位字段 - 若字段名不一致,通过
@JsonProperty("mail")注解找到真实字段 -
field.setAccessible(true)后调用field.set(instance, value)赋值 - 遇到嵌套类型(如字段是
Address),递归走同样流程——全程依赖反射导航类型树
✅ 关键点:你传入的
clazz是运行时才知道的,比如从字符串"com.example.User"通过Class.forName(className)加载而来。
手动用反射实现简易版(仅作理解,不推荐生产)
public static String serialize(Object obj) throws Exception {
Class> clazz = obj.getClass();
StringBuilder json = new StringBuilder("{");
Field[] fields = clazz.getDeclaredFields();
for (int i = 0; i <p>⚠️ 注意:这没处理 null、嵌套对象、集合、类型转换、注解、循环引用等——正是 Gson/Jackson 用反射+大量策略封装的价值所在。</p><hr><h3><strong>注意事项</strong></h3>
-
setAccessible(true)在 JDK 12+ 受强封装限制,需添加 JVM 参数(如--illegal-access=permit)或改用MethodHandles(Jackson 已适配) - 泛型信息(如
List<string></string>)在运行时被擦除,需配合TypeReference或ParameterizedType+ 反射提取真实类型 -
transient字段默认跳过;static字段不参与序列化——反射扫描时会自然过滤(getDeclaredFields()返回所有字段,但框架逻辑会判断修饰符) -
serialVersionUID是 Java 原生序列化专用,JSON 框架完全不依赖它
不复杂但容易忽略
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











