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.rhkb.cn/news/339202.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈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);字符串比较 比较 比较的是两个…

隐马尔可夫链

1 马尔可夫链 马尔科夫链&#xff08;Markov Chain&#xff09;是一种数学模型&#xff0c;它描述了一系列可能事件的概率&#xff0c;其中每个事件的发生仅依赖于前一个事件的状态。这一特性称为“无记忆性”或“马尔可夫性质”。我将用一个简单的天气预测模型作为例子来解释马…

Java+SVNCloud+Mysql课程设计

文章目录 1、主要内容2、所需准备3、与sql访问的中间类&#xff1a;SqlMessage4、窗口界面5、main方法 1、主要内容 课程设计&#xff0c;主要通过Javas wing创建窗口&#xff0c;jdbc连接云端mysql数据库进行基本操作&#xff0c;支持随机生成数据并用动态展示数据结果。 先…

自学 Java 怎么入门?

关于自学 Java 如何入门这一重要课题&#xff0c;在此为大家进行详细阐述。 在此之前&#xff0c;如果大家有兴趣的话&#xff0c;可以看看我自己精心整理的嵌入式入门资料&#xff0c;这些资料将全部免费送给大家。其中包含了编程教学内容、详细的视频讲解、实用的数据库资料…

Vue 实例

一、页面效果图 二、代码 <!DOCTYPE html> <html><head><meta charset"utf-8"><script src"../vue.js" type"text/javascript"></script><title>vue 实例</title></head><body>&l…

Linux命令篇(一):文件管理部分

&#x1f49d;&#x1f49d;&#x1f49d;首先&#xff0c;欢迎各位来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里不仅可以有所收获&#xff0c;同时也能感受到一份轻松欢乐的氛围&#xff0c;祝你生活愉快&#xff01; 文章目录 1、cat命令常用参…

HALCON-从入门到入门-图像格式的互相转换

1.废话 上次说到了图片的读取和写入到本地&#xff0c;这次说一下图片的格式相关。 位图和矢量图 photoshop处理出来的图片肯定叫做图片&#xff0c;那么coreDraw处理出来的图片是不是也叫图片。 之间就有区分&#xff0c;一种叫做位图&#xff0c;一种叫做矢量图 位图和矢…

创建一个支持切换阅读模式和答题模式的Anki问答题模板

为了备考某个需要默写的科目&#xff0c;做了个问答题笔记模板&#xff0c;如下&#xff1a; 在上图的回答栏填写答案后&#xff0c;点击显示答案按钮转到背面&#xff1a; 只实现上面的功能是很简单的&#xff0c;直接基于Anki自带的问答题模板添加自己需要的字段即可。问题…

基于卷积-小波神经网络的SAR图像海冰变化检测方法(MATLAB R2018A)

海冰是冰冻圈的重要组成部分&#xff0c;海冰的变化信息对航行安全和自然资源开采等非常重要&#xff0c;许多船舶没有加固防冰设备&#xff0c;因此&#xff0c;必须避开所有的冰区。尤其当冰压很高时&#xff0c;即使破冰船也很难在冰层中前行。为了安全航行&#xff0c;获取…

自动化办公01 smtplib 邮件⾃动发送

目录 一、准备需要发送邮件的邮箱账号 二、发送邮箱的基本步骤 1. 登录邮箱 2. 准备数据 3. 发送邮件 三、特殊内容的发送 1. 发送附件 2. 发送图片 3. 发送超文本内容 4.邮件模板内容 SMTP&#xff08;Simple Mail Transfer Protocol&#xff09;即简单邮件传输协议…

天气数据集-Jena Climate dataset

天气数据集-Jena Climate dataset 1.数据集基本信息 Dataset Name: mpi_saale_2021b.csv Size: 26495 rows; 1 year (2021), 10 min 气象学、农业、环境科学 开源机构: Max Planck Institute for Biogeochemistry 2.数据特征 2.1 特征简介 数据共有31个特征&#xff0c;…

使用 Scapy 库编写 Ping of Death 攻击脚本

一、介绍 1.1 概述 Ping of Death&#xff08;PoD&#xff09;攻击是一种历史悠久的拒绝服务&#xff08;DoS&#xff09;攻击&#xff0c;攻击者通过发送特制的畸形ICMP Echo请求数据包&#xff0c;导致目标系统无法正确处理&#xff0c;从而导致系统崩溃、重启或无法响应正…

【最新鸿蒙应用开发】——什么是状态管理?

状态管理 在声明式UI编程框架中&#xff0c;UI是程序状态的运行结果&#xff0c;用户构建了一个UI模型&#xff0c;其中应用的运行时的状态是参数。当参数改变时&#xff0c;UI作为返回结果&#xff0c;也将进行对应的改变。这些运行时的状态变化所带来的UI的重新渲染&#xf…

【Postman接口测试】第四节.Postman接口测试项目实战(上)

文章目录 前言一、项目介绍 1.1 项目界面功能介绍 1.2 项目测试接口介绍 1.3 项目测试接口流程二、HTTP协议三、接口测试中接口规范四、项目合同新增业务介绍 4.0 接口测试用例设计流程 4.1 登录接口调试 4.2 登录接口自动关联 4.3 添加…

攻防世界---web---Web_php_unserialize

1、题目描述 2、 3、分析代码 class Demo { private $file fl4g.php; }&#xff1a;定义了一个名为Demo的类&#xff0c;该类有一个私有属性$file&#xff0c;默认值为fl4g.php。 $a serialize(new Demo);&#xff1a;创建了一个Demo类的实例&#xff0c;并对其进行序列化&a…

【机器学习】基于OpenCV和TensorFlow的MobileNetV2模型的物种识别与个体相似度分析

在计算机视觉领域&#xff0c;物种识别和图像相似度比较是两个重要的研究方向。本文通过结合深度学习和图像处理技术&#xff0c;基于OpenCV和TensorFlow的MobileNetV2的预训练模型模&#xff0c;实现物种识别和个体相似度分析。本文详细介绍该实验过程并提供相关代码。 一、名…

eNSP学习——VRRP基础配置

目录 主要命令 原理概述 实验目的 实验内容 实验拓扑 实验编址 实验步骤 1、基本配置 2、部署OSPF网络 3、配置VRRP协议 4、验证VRRP主备切换 主要命令 //创建备份组 [R2]int g0/0/1 [R2-GigabitEthernet0/0/1]vrrp vrid 1 virtual-ip 192.168.1.254 //修改优先级 …

自动评论自动私信引流系统,自动化时代的挑战与机遇

随着科技的飞速发展&#xff0c;自动化技术已经渗透到我们生活的方方面面。从工业生产线上的机械臂到家庭中的智能助手&#xff0c;自动化不仅改变了我们的工作方式&#xff0c;也在重塑着社会的面貌。然而&#xff0c;在享受自动化带来的便利和效率的同时&#xff0c;我们也必…

Java实现对PDF、纵向、横向页面添加自定义水印功能

Java实现对PDF、纵向、横向页面添加自定义水印 效果图 -- 纵向 页面PDF使用到JAR Maven依赖版本效果图 -- 横向页面PDF 效果图 – 纵向 页面PDF 代码如下&#xff1a; 使用到JAR Maven依赖版本 <dependency><groupId>org.apache.pdfbox</groupId><artifa…

FLINK-窗口算子

参考资料 官方文档- WindowFlink中的时间和窗口之窗口 窗口 在流处理中&#xff0c;我们往往需要面对的是连续不断、无休无止的无界流&#xff0c;不可能等到所有所有数据都到齐了才开始处理。所以聚合计算其实只能针对当前已有的数据——之后再有数据到来&#xff0c;就需要继…