当前位置: 首页 > news >正文

【TypeReference<目标泛型类型>】

TypeReference是 FastJSON(阿里)提供的核心工具类,专门解决Java 泛型类型擦除问题,让 JSON 解析时能正确识别泛型(比如List<User>ModelMessage<Map>),而不是解析成原始的Object

一、先理解核心痛点:为什么需要 TypeReference?

Java 泛型是“编译时有效,运行时擦除”的——比如List<String>运行时会变成List,直接用JSON.parseObject(json, List.class)解析,得到的是List<Object>,而非List<String>

TypeReference的作用就是保存泛型的真实类型信息,让 FastJSON 能精准解析出带泛型的对象。

二、TypeReference 基础用法(从易到难)

1. 最简写法(JDK 8+ 支持菱形语法)
importcom.alibaba.fastjson.JSON;importcom.alibaba.fastjson.TypeReference;importjava.util.List;importjava.util.Map;publicclassTypeReferenceDemo{publicstaticvoidmain(String[]args){// 示例1:解析简单泛型(List<String>)Stringjson1="[\"Java\",\"FastJSON\",\"TypeReference\"]";// 核心写法:new TypeReference<目标泛型类型>() {}List<String>strList=JSON.parseObject(json1,newTypeReference<List<String>>(){}// 注意末尾的 {},必须加!);System.out.println(strList.get(0));// 输出:Java(类型是 String,而非 Object)// 示例2:解析嵌套泛型(Map<String, Integer>)Stringjson2="{\"age\":25,\"score\":98}";Map<String,Integer>intMap=JSON.parseObject(json2,newTypeReference<Map<String,Integer>>(){});System.out.println(intMap.get("age")+1);// 输出:26(Integer 可直接运算)}}
2. 解析自定义泛型类(比如ModelMessage

假设自定义泛型类是:

// 自定义泛型类classModelMessage<T>{privateModelHeaderheader;privateTbody;// 泛型 body,可能是 Map、String、List 等// 省略 getter/setterpublicModelHeadergetHeader(){returnheader;}publicvoidsetHeader(ModelHeaderheader){this.header=header;}publicTgetBody(){returnbody;}publicvoidsetBody(Tbody){this.body=body;}}// 辅助类classModelHeader{privateStringrequestId;privateStringtimestamp;// 省略 getter/setter}

TypeReference解析ModelMessage<Map<String, Object>>

publicclassCustomGenericDemo{publicstaticvoidmain(String[]args){// 模拟你的 JSON 数据Stringjson="{\"header\":{\"requestId\":\"123\",\"timestamp\":\"20260313\"},\"body\":{\"name\":\"张三\",\"age\":25}}";// 关键:指定完整泛型类型 ModelMessage<Map<String, Object>>TypeReference<ModelMessage<Map<String,Object>>>typeRef=newTypeReference<ModelMessage<Map<String,Object>>>(){};// 解析后直接得到带泛型的对象ModelMessage<Map<String,Object>>message=JSON.parseObject(json,typeRef);// 直接使用,无需手动类型转换System.out.println(message.getHeader().getRequestId());// 输出:123System.out.println(message.getBody().get("name"));// 输出:张三System.out.println(message.getBody().get("age"));// 输出:25(类型是 Integer)}}
3. 进阶:动态指定泛型类型(可选)

如果泛型类型需要动态调整(比如有时是Map,有时是List),可以封装成方法:

// 通用解析方法publicstatic<T>TparseJson(Stringjson,TypeReference<T>typeRef){returnJSON.parseObject(json,typeRef);}// 调用示例publicstaticvoidmain(String[]args){Stringjson="{\"header\":{},\"body\":[\"篮球\",\"读书\"]}";// 解析 body 为 List<String> 的情况ModelMessage<List<String>>message=parseJson(json,newTypeReference<ModelMessage<List<String>>>(){});System.out.println(message.getBody().get(0));// 输出:篮球}

三、关键细节(必看,避坑!)

  1. 必须加{}new TypeReference<...>() {}末尾的大括号不能少!

    • 原理:TypeReference是抽象类,{}是创建匿名子类,子类会保留泛型的类型信息(绕过类型擦除)。
    • 错误写法:new TypeReference<List<String>>()(编译报错,抽象类不能直接实例化)。
  2. 泛型嵌套也能解析:支持多层泛型,比如TypeReference<Map<String, List<User>>>

  3. 和直接传 Class 的区别

    • JSON.parseObject(json, List.class)→ 得到List<Object>(丢失泛型)。
    • JSON.parseObject(json, new TypeReference<List<String>>() {})→ 得到List<String>(保留泛型)。
  4. 处理 null 值:如果 JSON 字段是null(比如你之前的{"entities":null,"text":null}),解析后对应字段也是null,不会报错,可通过if (xxx != null)安全判断。

四、实战场景(对应你的需求)

针对你之前的{"entities":null,"text":null},用TypeReference解析:

// 假设你的目标类型是 ModelMessage<Map<String, Object>>StringyourJson="{\"header\":null,\"body\":{\"entities\":null,\"text\":null}}";TypeReference<ModelMessage<Map<String,Object>>>typeRef=newTypeReference<ModelMessage<Map<String,Object>>>(){};ModelMessage<Map<String,Object>>message=JSON.parseObject(yourJson,typeRef);// 安全取值(避免 null 空指针)Map<String,Object>body=message.getBody();if(body!=null){Objectentities=body.get("entities");// nullObjecttext=body.get("text");// nullSystem.out.println("entities: "+entities+", text: "+text);}

总结

  1. 核心作用:解决 Java 泛型擦除,让 FastJSON 能解析带泛型的对象(如List<String>ModelMessage<Map>)。
  2. 核心写法new TypeReference<目标泛型类型>() {}(末尾{}必须加)。
  3. 使用场景:只要解析的目标类型包含泛型(非简单的String/Integer/自定义普通类),就用TypeReference,否则直接用JSON.parseObject(json, 普通类.class)即可。
http://www.jsqmd.com/news/478685/

相关文章:

  • Web前端开发技术作业随笔
  • openclaw系列1:安装
  • 开发一个简单的脚手架
  • TestPilot - 智能测试用例生成工具
  • 什么是DAS分布式光纤声波传感系统?原理与应用解析
  • 大数据领域Doris在医疗科技领域的临床数据分析
  • Flutter 三方库 hotp 的鸿蒙适配指南 - 实现 RFC 4226 标准双因素认证、在 OpenHarmony 上打造极致安全的动态令牌实战
  • 汽油生产
  • 必看!AI拓客软件源头厂家哪家强?
  • Java大厂面试实录:谢飞机的搞笑面试之旅
  • Python当中ascii码与字母的相互转换
  • 深度学习之循环神经网络RNN
  • VMware安装RedHat Linux9全攻略
  • LeeCode4.寻找两个正序数组的中位数。小白都能懂。
  • JAVA基础二
  • ContentProvider与Uri权限:跨应用数据共享
  • 攻防世界 misc题心仪的公司
  • Linux:进程调度
  • 软件测试定义、目的、调试、需求概念、软件生命周期与测试流程
  • 学习率调度的艺术:从Warmup到余弦退火,掌握深度学习的训练节奏
  • AI 辅助编程阶段化开发 SOP
  • 大数据安全必修课:数据隐私保护的7大核心原则
  • 56767786
  • 工业缺陷检测的新范式:2025-2026年零样本检测技术全景扫描
  • 51单片机的【智能火灾报警系统】仿真设计
  • 北京营养自愈力专家亲测分享:这样找最靠谱!
  • 代码上传到gitee
  • 我不知道起什么我就是找个地方说话
  • 量化开发实战手册·第1篇:数据源选型指南——如何为你的策略找到最合适的行情接口?
  • Flutter 三方库 flutter_localized_locales 鸿蒙适配指南 - 实现工业级全球化多语言映射与区域感知实战