码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • 掌握 TypeToken 原理及泛型擦除


    目录

    1、泛型擦除

    为什么选择这种实现机制?不擦除不行么?

    2、TypeToken

    1、为什么要用TypeToken来定义反序列化的类型?

    2、为什么带有大括号{}?

     3、为什么要通过子类来获取泛型的类型?

    3、原理


    1、泛型擦除

    众所周知,Java的泛型只在编译时有效,到了运行时这个泛型类型就会被擦除掉,即List和List在运行时其实都是List类型。

    代码测试

    1. @Test
    2. public void test(){
    3. ArrayList list1 = new ArrayList<>();
    4. ArrayList list2 = new ArrayList<>();
    5. System.out.println(list1.getClass());
    6. System.out.println(list2.getClass());
    7. }

    为什么选择这种实现机制?不擦除不行么?

    在Java诞生10年后,才想实现类似于C++模板的概念,即泛型。Java的类库是Java生态中非常宝贵的财富,必须保证向后兼容(即现有的代码和类文件依旧合法)和迁移兼容(泛化的代码和非泛化的代码可互相调用)基于上面这两个背景和考虑,Java设计者采取了“类型擦除”这种折中的实现方式。

    同时正有这个这么“坑”的机制,令我们无法在运行期间随心所欲的获取到泛型参数的具体类型。

    2、TypeToken

    使用过Gson的同学都知道在反序列化时需要定义一个TypeToken类型,像这样

    1. Type type = new TypeToken>() {}.getType();
    2. List list1 = gson.fromJson(listJsonString, type);

    三个问题

    1、为什么要用TypeToken来定义反序列化的类型?

    正如上面说的,如果直接把 ArrayList 的类型传过去,因为运行时泛型被擦除了,所以得到的其实是 ArrayList ,那么后面的Gson就不知道要转成 ArrayList 类型了。

    2、为什么带有大括号{}?

    这个大括号就是精髓所在。大家都知道,在Java语法中,在这个语境,{}是用来定义匿名类,这个匿名类是继承了TypeToken类,它是TypeToken的子类。

    测试 

    1. @Test
    2. public void test2(){
    3. System.out.println(new TypeToken>() {}.getClass().getSuperclass());
    4. }

     结果

     3、为什么要通过子类来获取泛型的类型?

    这是TypeToken能够获取到泛型类型的关键,这是一个巧妙的方法。这个想法是这样子的,既然像ArrayList 这样中的泛型会被擦除掉,那么我用一个子类 SubList extends ArrayList这样的话,在JVM内部中会不会把父类泛型的类型给保存下来呢?

    我这个子类需要继承的父类的泛型都是已经确定了的呀,果然,JVM是有保存这部分信息的,它是保存在子类的Class信息中。

    那么我们怎么获取这部分信息呢?还好,Java有提供API出来

    1. public class TestMethod {
    2. @Test
    3. public void test1(){
    4. Student student = new Student();
    5. /**
    6. * getGenericSuperclass()获得带有泛型的父类
    7. * Type是 Java 编程语言中所有类型的公共高级接口。它们包括原始类型、参数化类型、数组类型、类型变量和基本类型。
    8. */
    9. Type mySuperClass = student.getClass().getGenericSuperclass();
    10. Type type = ((ParameterizedType) mySuperClass).getActualTypeArguments()[0];
    11. System.out.println(type);
    12. }
    13. }
    14. class Student extends ArrayList>{
    15. }

     

     概括来说就是对于带有泛型的class,返回一个ParameterizedType对象,对于Object、接口和原始类型返回null,对于数组class则是返回Object.class。

    ParameterizedType是表示带有泛型参数的类型的Java类型,JDK1.5引入了泛型之 后,Java中所有的Class都实现了Type接口,ParameterizedType则是继承了Type接口,所有包含泛型的Class类都会实现 这个接口。

    3、原理

    getType方法

    1. public final Type getType() {
    2. return this.type;
    3. }

    type的初始化

    protected的作用范围是在同一包内可被访问和继承。不同包内,子类可继承,非子类不能访问

    由于是第三方 jar 包,所以只有子类才能访问。

    1. protected TypeToken() {
    2. this.type = getSuperclassTypeParameter(getClass());
    3. this.rawType = (Classsuper T>) $Gson$Types.getRawType(type);
    4. this.hashCode = type.hashCode();
    5. }

    getSuperclassTypeParameter方法

    里面的代码就是上面说到的获取父类泛型参数的方法

    1. static Type getSuperclassTypeParameter(Class subclass) {
    2. Type superclass = subclass.getGenericSuperclass();
    3. if (superclass instanceof Class) {
    4. throw new RuntimeException("Missing type parameter.");
    5. }
    6. ParameterizedType parameterized = (ParameterizedType) superclass;
    7. //这里注意一下,返回的是Gson自定义的,这个类是继承Type的。
    8. return Types.canonicalize(parameterized.getActualTypeArguments()[0]);
    9. }

    在了解原理之后,相信大家都知道怎么去获取泛型的类型了。

    参考文章:掌握 Java-TypeToken 原理及泛型擦除-Java知音 (javazhiyin.com)

  • 相关阅读:
    uni-app 前端项目(vue)部署到本地win系统Nginx上
    ArcGIS按点提取栅格
    asp.net core项目部署到iis每次更新都提示被占用需要停止网站才可以的问题解决
    JAVA二叉搜索树(专门用来查找)
    Java中的23种设计模式
    HTML5,CSS,JS前端常见知识面试题
    音频类型转换工具-可执行文件exe/dmg制作
    VSCode设置用户自定义代码片段(给代码片段设置成快捷键)快捷代码设置方法
    docker应用部署---Tomcat的部署配置
    高防服务器防护效果怎么样?
  • 原文地址:https://blog.csdn.net/qq_51409098/article/details/126224264
    • 最新文章
    • 【JVM】编译执行与解释执行的区别是什么?JVM 使用哪种方式?
      用 Hashids 优雅解决 C 端自增 ID 暴露问题
      V8引擎 精品漫游指南--Ignition篇(上) 指令 栈帧 槽位 调用约定 内存布局 基础内容
      LLVM Pass快速入门(四):代码插桩
      milkup:桌面端 markdown AI续写和即时渲染
      基于项目工程构建SBOM(软件物料清单)的研究
      鸿蒙应用开发UI基础第二节:鸿蒙应用程序框架核心解析与实操
      .NET 中如何快速实现 List 集合去重?
      扣子Coze实战:从0到1打造抖音+小红书热点监控智能体
      浅谈数据访问层
    • 热门文章
    • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
      奉劝各位学弟学妹们,该打造你的技术影响力了!
      五年了,我在 CSDN 的两个一百万。
      Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
      面试官都震惊,你这网络基础可以啊!
      你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
      心情不好的时候,用 Python 画棵樱花树送给自己吧
      通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
      13 万字 C 语言从入门到精通保姆级教程2021 年版
      10行代码集2000张美女图,Python爬虫120例,再上征途
    小工具 小游戏
    Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1

    京公网安备 11010502049817号