Fastjson 的 TypeReference 通过匿名子类保留泛型签名,但仅对编译期已知类型有效;运行时动态类型需用带参构造器 new TypeReference(actualClass) {} 显式传入最内层 Class,且从 1.2.9+ 支持,外层结构仍须完整写出。

Fastjson 的 TypeReference 是解决多层嵌套泛型反序列化的关键工具,但直接写 new TypeReference 往往不够——尤其当 T 是运行时才确定的具体类型(比如 UserDTO 或 Order)时,泛型擦除会让 Fastjson 无法识别最内层类型,导致 data 字段解析成 JSONObject 而非真实对象,强转即抛 ClassCastException。
为什么单层 TypeReference 对 Response 失效
Java 编译后会擦除所有泛型信息。虽然 TypeReference 利用匿名子类保留了字节码中的泛型签名,但它只能“看到”编译期已知的完整类型结构。如果代码里写的是:
-
JSON.parseObject(json, new TypeReference→ ✅ 可行,因为>>() {}) UserDTO是具体类,签名完整 -
JSON.parseObject(json, new TypeReference→ ❌ 编译不通过或运行时>>() {}) T被擦成Object,Page.records仍为JSONObject
正确传入运行时确定的泛型参数
当 T 来自方法参数、配置或反射结果时,必须用 TypeReference 的带参构造器显式注入实际类型:
使用约定式提交(Conventional Commits)生成标准化的 Git 提交信息。适用于以下场景: (1) 暂存更改时需要提交信息; (2) 审查 diff 时希望获得结构化摘要; (3) 编写 PR 描述或变更日志(changelog)条目; (4) 用户明确要求“为本次更改编写提交信息”。 该功能会分析已暂存/未暂存的 diff,并生成按类型(type)划分范围的提交信息。
- Fastjson 支持
new TypeReference,其中>>(actualClass) {} actualClass是UserDTO.class这样的Class对象 - 示例:
Response
> result = JSON.parseObject(json, new TypeReference >>(UserDTO.class) {}); - 注意:这个构造器从 Fastjson 1.2.9+ 开始支持,且只作用于最内层泛型变量(即
T),外层结构(Response)仍需完整写出>
三层及以上嵌套的典型写法
面对 Response 这类结构,不要试图嵌套多层泛型变量,而是逐级“展开”并指定最末端的实际类型:
- 错误:
new TypeReference——>>>(Item.class) {} List中的T可被替换,但Page和List本身不能动态化 - 正确:
new TypeReference(全部写死)>>>() {} - 更灵活:
new TypeReference+ 提前构建>>>() {} ParameterizedType(适用于高度动态场景)
避免重复反射开销:缓存 Type 实例
TypeReference.getType() 每次调用都会触发反射解析,高频调用时建议缓存:
- 声明为
static final: private static final Type USER_RESPONSE_TYPE = new TypeReference>>() {}.getType(); - 使用时直接传入:
Response
> r = JSON.parseObject(json, USER_RESPONSE_TYPE); - 若类型动态,可基于
Class参数生成并缓存在ConcurrentHashMap中,避免重复解析
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










