kotlin1.8.10问题导致gson报错TypeToken type argument must not contain a type variable

书接上回,https://blog.csdn.net/jzlhll123/article/details/139302991。
之前我发现gson报错后:
gson在2.11.0给我的kotlin项目代码报错了。

IllegalArgumentException: TypeToken type argument must not contain a type variable

上次解释原因是因为,gson内部有了报错,根本原因就是二级嵌套泛型获取的解析方式问题。而且写下了解决办法和参考代码。 是错误的。
我后来又通过在demo工程中尝试,怎么都无法复现,困扰了我好几天。我又去研究了字节码和反编译。
最后发现,

public class ApiBean {public String type;public String name;public String url;
}public class CmdBean<T>  { //T就可以传入ApiBean做为二层嵌套泛型public String cmdId;public long ts;public String pro;public T apiBean;
}//二层嵌套解析 //暂时有问题。后面会讲到他没问题
inline fun <reified T> parse(jsonStr: String?): CmdBean<T>? {return jsonStr?.fromJson<CmdBean<T>>()
}//二层嵌套解析 //暂时有问题。后面会讲到他没问题
inline fun <reified T> parseList(jsonStr: String?): List<T>? {return jsonStr?.fromJson<List<T>>()
}//通用函数 //暂时有问题。后面会讲到他没问题
inline fun <reified T> String.fromJson(): T {return Globals.gson.fromJson(this, object : TypeToken<T>() {}.type)
}class Action {fun test() {val json = """
{"apiBean":{"name":"nameX","type":"typeX","url":"htpps://api.....com/.../..xxx"},"cmdId":"cmdId010102394","pro":"aaaa","ts":1029301291023}""".trimIndent()val cmd = parse<ApiBean>(json)println("cmd $cmd")}fun testList() {val json = """
[{"name":"icon1","type":"type1","url":"https://.......png"},{"name":"icon2","type":"type2","url":"https://..xx.....png"}]""".trimIndent()val cmd = parseList<ApiBean>(json)println("list $cmd")}
}

上述代码是很简单的,主要就是有一个嵌套的解析:
parse<ApiBean>(json), parse函数内部,就是jsonStr?.fromJson<CmdBean<T>>()这样嵌套去解析。然后这个函数又经过一个普通的封装函数fromJson来解析。
在本地kotlin版本

 id 'org.jetbrains.kotlin.android' version '1.8.10' apply false//也可能写作:kotlin = "1.8.10"jetbrains-kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }

在1.8.10之下:
编译查看class:
请添加图片描述请添加图片描述请添加图片描述由此,我们就能知道为什么会报错了。原因就是字节码写了new出来的匿名内部类是个带T的,所以因为JVM上泛型擦除出现了T,gson的TypeToken就无法解析到真实的类,因此出现了问题。当我反复对比找各种原因,最后终于怀疑到了版本上。修改到kotlin1.8.20,kotlin1.9.0, kotlin 1.9.24均发现ok 了。对比的图如下:请添加图片描述
请添加图片描述
请添加图片描述
很明显,对于这种嵌套型的inline+reified从kotlin1.8.20开始,生成的内部类就不会再有问题。

并且,gson官方文档提到的解决方案:

Use TypeToken.getParameterized(...), for example TypeToken.getParameterized(List.class, elementType) where elementType is a type you have to provide separately.
For Kotlin users: Use reified type parameters, that means change <T> to <reified T>, if possible. If you have a chain of functions with type parameters you will probably have to make all of them reified.

其实对于kotlin项目而言,

inline fun <reified T> String.fromJson(): T {return Globals.gson.fromJson(this, object : TypeToken<T>() {}.type)
}

这个函数就是完美的,
你可以直接传入fromJson<List<Bean>(), 可以传入fromJson<CmdBean<InnerBean>()的形式,他就能给你处理好。

而非kotlin的java项目,你就不得不按照官方

public static <T> T parse(String jsonStr, Class<T> t) {return new GsonBuilder().create().fromJson(jsonStr, t);
}public static <T, T2> MyCmd<T2> parseLv2(String jsonStr, Class<T> t, Class<T2> t2) {Type typeToken = TypeToken.getParameterized(t, t2).getType();return new GsonBuilder().create().fromJson(jsonStr, typeToken);
}

或者参考我上篇帖子https://blog.csdn.net/jzlhll123/article/details/139302991的三个解决方案。
java中就不会遇到kotlin编译内部类的问题了。
而是可能会犯低级错误:
比如

        var json = """
{"apiBean":{"name":"nameX","type":"typeX","url":"htpps://api.....com/.../..xxx"},"cmdId":"cmdId010102394","pro":"aaaa","ts":1029301291023}""";var cmd = parse(json, CmdBean.class); //错误,没有提供二级泛型。需要TypeToken.getParameterized等方式解析。System.out.printf("cmd " + cmd);val listCmd = parse(json, List.class) //错误,没有提供二级泛型。需要TypeToken.getParameterized等方式解析。

因为是嵌套泛型,必须得提供二级泛型的解析,这里容易错误。

而kotlin,由于inline和reified就可以解决它,前提是你要注意kotlin的版本哟,1.8.10有坑!1.8.20开始好的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/21401.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

String常用操作

String常用方法 构造字符串 常用的构造字符串有3种&#xff1a; 1.直接赋值String s "abcd"; 2.实例化调用构造方法String s new String("abcd"); 3.实例化传字符数组 char[] ch {a,b,c,d}; String s new String(ch);字符串比较 比较 比较的是两个…

35【Aseprite 作图】苹果——拆解

1 叶子是&#xff0c;竖着4&#xff0c;然后2 1 竖2&#xff1b;左边是1 2 横着2&#xff1b;然后横着连接 之后画苹果&#xff0c;4 3 1 1 1 &#xff0c;竖着8 2 1 1 1 2 横着5&#xff1b;之后水平翻转&#xff08;苹果左右一样&#xff09; 2 加上浅绿做底色 3 阴影部分 …

C语言 | Leetcode C语言题解之第128题最长连续序列

题目&#xff1a; 题解&#xff1a; typedef struct {int key;UT_hash_handle hh; }Hash; int longestConsecutive(int* nums, int numsSize) {Hash* headNULL;Hash* tempNULL;for(int i0;i<numsSize;i){int numnums[i];HASH_FIND_INT(head,&num,temp);if(!temp){temp…

HCIP的学习(27)

RSTP—802.1W—快速生成树协议 STP缺陷&#xff1a; 1、收敛速度慢----STP的算法是一种被动的算法&#xff0c;依赖于计时器来进行状态变化 2、链路利用率低​ RSTP向下兼容STP协议。&#xff08;STP不兼容RSTP&#xff09; 改进点1—端口角色 802.1D协议---根端口、指定端口…

驾校-短视频营销招生精品课:抖音推广技巧,抖音短视频招生(41节课)

课程下载&#xff1a;驾校-短视频营销招生精品课&#xff1a;抖音推广技巧&#xff0c;抖音短视频招生(41节课)-课程网盘链接提取码下载.txt资源-CSDN文库 更多资源下载&#xff1a;关注我。 课程内容&#xff1a; 课程目录 [1]-第1课驾校为什么要全力做好短视频营销.mp4 …

Word2021中的The Mathtype DLL cannot be found问题解决(office 16+mathtype7+非初次安装)

问题描述&#xff0c;我的问题发生在word中无法使用自定义功能区中的mathtype 我的环境是&#xff1a;W11Word2021mathtype7 因为我是第二次安装mathtype7&#xff0c;所以我怀疑是因为没有卸载干净&#xff0c;于是我参考了下面这篇文章的做法 参考文章 1.首先重新卸载当前的…

Go语言学习记录

GO语法学习之路 学习时间段2024-06-02学习记录安装&环境配置Go安装包内容统一入门姿势&#xff1a;hello world实现 Go语法初学Go 运行时&#xff08;runtime&#xff09;Go解释器 学习时间段 #mermaid-svg-tTuVZ3bbdJvu04kX {font-family:"trebuchet ms",verdan…

每日一练——分糖果

575. 分糖果 - 力扣&#xff08;LeetCode&#xff09; 方法一 可以做&#xff0c;但提示超时了 #define MIN(x, y) (x < y ? x : y)int distributeCandies(int* candyType, int candyTypeSize) {int p 0;char flag 1;for (int i 1; i < candyTypeSize; i){for (int…

Java项目:94 springboot大学城水电管理系统

作者主页&#xff1a;源码空间codegym 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文中获取源码 项目介绍 本管理系统有管理员和用户。 本大学城水电管理系统管理员功能有个人中心&#xff0c;用户管理&#xff0c;领用设备管理&#xff0c;消耗设备…

基于51单片机的俄罗斯方块

一.硬件方案 本设计采用STC89C52RC单片机作为系统的芯片&#xff0c;实现人机交互、娱乐等功能。选用LCD12864实现俄罗斯方块游戏界面、图形显示&#xff1b;选用独立按键实现游戏控制。本设计实现的基本功能是&#xff1a;用按键控制目标方块的变换与移动&#xff1b;消除一行…

OpenCASCADE开发指南<十四>:OCCT建模类之BRepPrimAPI_MakePipe创建管道

1、OpenCasCade拓扑几何 在Open CASCADE Technology (OCCT) 中,除了基本三维几何体建模类BRepBuilderAPI外,还提供了复杂模型的建模类,常用的有如下几种,他们可以单独使用或相互组合,通过OCCT提供的融合函数进行组装。例如:BRepOffsetAPI_ThruSections、BRepOffsetAPI_Ma…

15 试用期,转正时我们要考察什么?

上一讲&#xff0c;我点出了“找人并不等于盲目加人”&#xff0c;你既要明确业务现状与团队需求&#xff0c;更要做好面试甄别&#xff0c;做出最优决定。那么当你找到人之后&#xff0c;是不是就可以高枕无忧了呢&#xff1f;并不是。 因为最终目的并非招聘&#xff0c;而是…

基于安卓的虫害识别软件设计--(2)模型性能可视化|混淆矩阵、热力图

1.混淆矩阵&#xff08;Confusion Matrix&#xff09; 1.1基础理论 &#xff08;1&#xff09;在机器学习、深度学习领域中&#xff0c;混淆矩阵常用于监督学习&#xff0c;匹配矩阵常用于无监督学习。主要用来比较分类结果和实际预测值。 &#xff08;2&#xff09;图中表达…

FPGA代码移植案例分析:Tcl Scripts后提示找不到 vo 文件,Supra软件报错

FPGA代码移植案例分析&#xff1a;Tcl Scripts后提示找不到 vo 文件&#xff0c;Supra软件报错 客户工程师已经运行Tcl Scripts&#xff0c;正常没出错就会产生这个vo文件。工程师试了两次 运行之后点的next的&#xff0c;还是出现同样的错误。 建议客户在原quartus工程里重新…

LabVIEW如何确保步进电机的长期稳定运行

步进电机因其良好的定位精度和控制性&#xff0c;在自动化设备中得到了广泛应用。然而&#xff0c;长期稳定运行对于任何电机系统都是一个重要的挑战。LabVIEW作为一款强大的图形化编程语言&#xff0c;通过其灵活的控制算法和实时监控能力&#xff0c;为步进电机的稳定运行提供…

探索 Vue Devtools 4.0 的新世界!

大家好&#xff0c;我是前端宝哥。Vue Devtools 4.0 版本带来了一系列激动人心的新特性和改进&#xff0c;让我们一起来探索这些更新亮点&#xff01; 宝哥省流版&#xff1a; &#x1f6e0; 直接编辑组件数据&#xff0c;实时预览变更效果。⚙️ 快速编辑功能&#xff0c;一键…

Python 基于机器学习模型的车牌检测和识别系统 有GUI界面 【含Python源码 MX_004期】

一、系统介绍 车牌的检测和识别技术在现代社会中的应用场景可谓十分广泛&#xff0c;不仅涉及交通管理领域&#xff0c;还延伸至社区安保等多个方面。例如&#xff0c;在交通违章管理中&#xff0c;通过车牌追踪可以有效追踪违章车辆&#xff0c;维护交通秩序&#xff1b;在小区…

如何高效管理团队任务?强大的在线管理团队多任务的神器-YesDev

任务是最小的工作项&#xff0c;工时是可以对研发产能进行量化。 一员工工时 工作组工时登记配置 针对于工作组&#xff0c;你可以开启/关闭工时登记。关闭工作组的工时登记后&#xff0c;整个工作组将取消工时登记&#xff0c;重新开启后恢复。 在同一个工作组内&#xff0c…

碰撞检测技术在AI中的重要作用

引言&#xff1a; 随着人工智能技术的不断发展&#xff0c;AI已经渗透到我们生活的方方面面。在游戏、机器人、虚拟现实等领域中&#xff0c;碰撞检测技术扮演着至关重要的角色。本文将探讨碰撞检测技术在AI中的作用&#xff0c;以及如何利用这项技术来改善AI系统的性能和用户体…

6,串口编程———通过串口助手发送数据,控制led亮灭

//功能&#xff1a;串口助手每次发送数据格式&#xff1a;0000& // 第二个字节控制LED1亮灭 // 第三个字节控制LED2亮灭 // 第四个字节控制LED3亮灭 // 第无个字节控制LED4亮灭 //要求&#xff1a;代码能够一直运行&#xff0c;能够接收多字节数据 上节讲了串口的基本…