java语法糖之泛型与类型擦除(代码片段)

JavaEdge. JavaEdge.     2023-01-03     555

关键词:

1 泛型与类型擦除

泛型,JDK 1.5新特性,本质是参数化类型(Parametersized Type) 的应用,即所操作的数据类型被指定为一个参数。这种参数类型可用在:

  • 接口
  • 方法

的创建中, 分别称为:

  • 泛型类
  • 泛型接口
  • 泛型方法

在Java还没有泛型的版本时。只能通过:

  1. Object 是所有类型的父类
  2. 类型强制转换

两个特性协作实现类型泛化。例如,在哈希表的存取中,JDK 1.5之前使用HashMap的get() 方法,返回值就是个Object。由于Java语言里面所有的类型都维承于java.lang.Object,所以Object转型成任何对象都有可能。但也因为有无限的可能性,就只有程序员和运行期的虚拟机才知道这个Objet到底是个什么类型的对象。
编译期间,编译器无法检查该Object的强制转型是否成功。若仅仅依赖程序员去保障正确性,许多ClassCastException的风险就会延迟到程序运行期。

Java语言中的泛型则不一样,它只在程序源码中存在,在编译后的字节码文件中,就已经替换为原来的原生类型(Raw Type) ,并在相应地方插入强制转换代码。
因此,对运行期的Java来说Araylist<int>Aralist<String>是同一个类。所以泛型是Java语言的一颗语法糖Java称为类型擦除,基于这种方法实现的泛型称为伪泛型。

  • 泛型擦除前的例子

    把这段Java代码编译成Class文件,然后再用字节码反编译后,將会发现泛型都不见了,又变回了Java泛型出现之前的写法,泛型类型都变回了原类型。如:

    通过擦除实现泛型,丧失了一些泛型思想应有的优雅
  • 当泛型遇见重载1

    不能被编译的,因为参数List<Integer>List<String>编译之后都被擦除了。变成了一样的原生类型List<E>,擦除动作导致这两种方法的特征签名变得一模一样。初步看来,无法重载的原因已经找到了,但真的就如此吗? 只能说,泛型擦除成相同的原生类型只是无法重载的部分原因
  • 当泛型遇见置载2

    由于Java泛型的引入,各种场景(虚拟机解析、反射等)下的方法调用都可能对原有基础产生影响,如在泛型类中如何获取传入的参数化类型等。因此,JCP组织对虚拟机规范做出了相应的修改,引入了诸如Signature、LocalVariableTypeTable 等新的属性用于解决伴随泛型而来的参数类型的识别问题,Signature 是其中最重要的一项属性,它的作用就是存储一个方法在字节码层面的特征签名,这个属性中保存的参数类型并不是原生类型,而是包括了参数化类型的信息。修改后的虚拟机规范要求所有能识别49.0以上版本的Class文件的虚拟机都要能正确地识别Signature参数。

从Signature属性的出现我们还可以得出结论,所谓的擦除,仅仅是对方法的Code属性中的字节码进行擦除,实际上元数据还是保留了泛型信息,这也是我们能通过反射取得参数化类型的根本依据。

  • 自动装箱: 拆箱与遍历循环
  • 自动装箱: 拆箱与遍历循环编译后
    遍历循环则把代码还原成了迭代器的实现,这也是为何遍历循环需要被遍历的类实现Iterable接口的原因。最后再看看变长参数,它在调用的时候变成了一个数组类型的参数,在变长参数出现之前,程序员就是使用数组来完成类似功能的。

java之泛型擦除

泛型擦除  在严格的泛型代码里,带泛型声明的类总应该带着类型参数。但为了与老的Java代码保持一致,也允许在使用带泛型声明的类时不指定类型参数。如果没有为这个泛型类指定泛型参数,则该类型参数被称作一个原始... 查看详情

kotlin实战之泛型与逆变协变总结(代码片段)

...部分不再列出。随着kotlin官方版本的迭代,文中有些语法可能会发生变化,请务必留意,语言领悟精髓即可,差异只是语法层面的 查看详情

java遗珠之泛型不可靠类型(代码片段)

不可靠类型可靠类型是在运行时包含所有完整信息的类型,包括原始类型,非泛型类型,原生类型和无边界通配符的调用。不可靠类型是编译时类型擦除移除了一些信息,比如不是无边界通配符的其他情况。一个... 查看详情

java遗珠之泛型不可靠类型(代码片段)

不可靠类型可靠类型是在运行时包含所有完整信息的类型,包括原始类型,非泛型类型,原生类型和无边界通配符的调用。不可靠类型是编译时类型擦除移除了一些信息,比如不是无边界通配符的其他情况。一个... 查看详情

第三节:java数据结构预备知识之泛型

...二节2:算法的时间复杂度和空间复杂度注意:泛型是Java语法中比较难掌握的部分,所以了解即可文章目录一:什么是泛型二:泛型语法(1)定义·(2)使用(3)例子三:泛型编译原理(1)擦除机制(2)为什么不能实例化泛型... 查看详情

java泛型与集合笔记

第一章Java的泛型为了兼容性和防止代码爆炸,在编译成字节碼时会进行类型擦除,编译器自动添加代码做类型转换(用到List<Integer>的地方用Integer来做转换),自动做装箱拆箱,做foreach替换,在多个参数的情况下自动打包... 查看详情

java遗珠之泛型七大限制(代码片段)

不能使用原始类型实例化泛型类型参数化类型如下:publicclassOrderedPair<K,V>implementsPair<K,V>privateKkey;privateVvalue;publicOrderedPair(Kkey,Vvalue)this.key=key;this.value=value;publicKgetKey()ret 查看详情

java遗珠之泛型类型推断(代码片段)

类型推断类型推断是java编译器的一种能力,通过查看方法调用和相应的声明来决定什么样的类型参数或者参数是更为合理的调用。推断算法先确定参数的类型,分配结果或者返回的类型,最终推断算法查找适合所有... 查看详情

java遗珠之泛型的作用(代码片段)

泛型总共有三个作用编译时进行更强大的类型检查编译时错误比运行时错误更好发现和处理消除类型转换Listlist=newArrayList();list.add("hello");Strings=(String)list.get(0);使用泛型之后去掉转换List<String>list=newArrayList<Str... 查看详情

java基础知识之泛型简单介绍(代码片段)

1、什么是java泛型?java泛型:英文名称是generics,泛型是jdk5引入的一个新特性,java泛型的本质就是参数化类型,就是所有的操作数据类型被指定为一个参数。对参数化类型进行操作的实体(例如类、接口... 查看详情

java基础知识之泛型简单介绍(代码片段)

1、什么是java泛型?java泛型:英文名称是generics,泛型是jdk5引入的一个新特性,java泛型的本质就是参数化类型,就是所有的操作数据类型被指定为一个参数。对参数化类型进行操作的实体(例如类、接口... 查看详情

java基础之泛型(代码片段)

泛型genericity格式:<自定义泛型无意义大写英文字母占位符>例:<T>Type<E>Element<K>Key<V>value泛型可以在方法,类,接口中使用泛型在方法中使用使用静态方法的泛型格式:publicstatic<T>返回值类型[自定义... 查看详情

java泛型:类型擦除(代码片段)

...1a;原始类型被限定类型替换类型擦除的限制无法利用同一泛型类的实例区分方法签名泛型类的静态变量是共享的类型擦除的特征问题导引这个例子里,定义了两个List集合,不过一个是List泛型类型的,只能存储整数;一... 查看详情

泛型与反射:type接口来历及子接口(代码片段)

泛型出现之前的类型没有泛型的时候,只有原始类型。此时,所有的原始类型都通过字节码文件类Class类进行抽象。Class类的一个具体对象就代表一个指定的原始类型。泛型出现之后的类型泛型是对类的抽象,泛型出... 查看详情

尝鲜dart2.7最新语法之泛型强化:声明处型变(代码片段)

...——泛型型变,可能有点深奥,但是确实是一个很重要的语法点。有关Dart泛型的知识,如果对Dart泛型没有深入了解过,强烈建议先把该专栏的第11篇内容学习下。如果你有过Kotlin、C#、Java的开发经验,对泛型协变、逆变、不变... 查看详情

java遗珠之泛型多边界(代码片段)

泛型的类型参数可以有多个边界<TextendsB1&B2&B3>当其中一个边界是class的时候需要写在前面。classA/*...*/interfaceB/*...*/interfaceC/*...*/publicclassD<TextendsA&B&C>/*...*/写在后面的话会有编译错误classD<TextendsB& 查看详情

java遗珠之泛型继承(代码片段)

当给定两个具体的类型A和B,MyClass<A>和MyClass<B>没有任何关系,不管A和B是什么关系。你可以通过扩展泛型类或者实现泛型接口的interfacePayloadList<E,P>extendsList<E>voidsetPayload(intindex,Pval);//...以下参数化的Payloa... 查看详情

java语法糖以及常见的应用(代码片段)

文章目录Java语法糖常见应用场景泛型与类型擦除自动装箱、拆箱与遍历循环条件编译变长参数增强for循环你在Java中使用过断言作为日常的判断条件吗?Java语法糖我们先了解一下语法糖的概念:语法糖(Syntacticsugar... 查看详情