Java语法关于泛型与类型擦除的分析

泛型与类型擦除

泛型,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组织对虚拟机规范做出了相应的修改,引入了诸如SignatureLocalVariableTypeTable 等新的属性用于解决伴随泛型而来的参数类型的识别问题,Signature 是其中最重要的一项属性,它的作用就是存储一个方法在字节码层面的特征签名,这个属性中保存的参数类型并不是原生类型,而是包括了参数化类型的信息。修改后的虚拟机规范要求所有能识别49.0以上版本的Class文件的虚拟机都要能正确地识别Signature参数。

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

  • 自动装箱: 拆箱与遍历循环

  • 自动装箱: 拆箱与遍历循环编译后

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

到此这篇关于Java语法关于泛型与类型擦除的分析的文章就介绍到这了,更多相关Java 泛型内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 半小时通透Java的泛型

    目录 前言 学习目标 1. 什么是泛型 2. 为什么需要泛型 3. 如何使用泛型 3.1 泛型使用 3.2 自定义泛型类 3.2.1 Java 源码中泛型的定义 3.2.2 自定义泛型类实例1 3.2.3 自定义泛型类实例2 3.3 自定义泛型方法 4. 泛型类的子类 4.1 明确类型参数变量 4.2 不明确类型参数变量 5. 类型通配符 5.1 无限定通配符 5.2 extends 通配符 5.3 super 通配符 6. 小结 Java 泛型 前言 编程不能停止,每天发一篇~ 不要捉急往后学

  • 详解Java类型擦除机制

    Java泛型是JDK 5引入的一个特性,它允许我们定义类和接口的时候使用参数类型,泛型在集合框架中被广泛使用.类型擦除是泛型中最让人困惑的部分,本篇文章将阐明什么是类型擦除,以及如何使用它. 一个常见错误 package simplejava; import java.util.ArrayList; public class Q29 { public static void main(String[] args) { ArrayList<String> al = new ArrayList&l

  • Java中的泛型

    目录 1. 什么是泛型 2. 为什么需要泛型 3. 如何使用泛型 3.1 泛型使用 3.2 自定义泛型类 3.2.1 Java 源码中泛型的定义 3.2.2 自定义泛型类实例1 3.2.3 自定义泛型类实例2 3.3 自定义泛型方法 4. 泛型类的子类 4.1 明确类型参数变量 4.2 不明确类型参数变量 5. 类型通配符 5.1 无限定通配符 5.2 extends 通配符 5.3 super 通配符 6. 小结 1. 什么是泛型 泛型不只是 Java 语言所特有的特性,泛型是程序设计语言的一

  • Java泛型的类型擦除示例详解

    目录 前言 泛型的类型擦除原则是: 1 擦除类定义中的类型参数 1.1 无限制类型擦除 1.2 有限制类型擦除 2 擦除方法定义中的类型参数 3 桥接方法和泛型的多态 总结 参考资料 前言 Java泛型这个特性是从JDK 1.5才开始加入的,因此为了兼容之前的版本,Java泛型的实现采取了"伪泛型"的策略,即Java在语法上支持泛型,但是在编译阶段会进行所谓的"类型擦除"(Type Erasure),将所有的泛型表示(尖括号中的内容)都替换为具体的类型(其对应的原生

  • 深入浅出理解Java泛型的使用

    目录 一.泛型的意义 二.泛型的使用 三.自定义泛型类 1.关于自定义泛型类.泛型接口: 2.泛型在继承方面的体现 3.通配符的使用 一.泛型的意义 二.泛型的使用 1.jdk 5.0新增特性 2.在集合中使用泛型: 总结: A.集合接口或集合类在jdk5.0时都修改为带泛型的结构. B.在实例化集合类时,可以指明具体的泛型类型. C.指明完以后,在集合类或接口中凡是定义类或接口时,内部结构(比如:方法.构造器.属性等)使用类的泛型的位置, 都指定为实例化的泛型类型.比如:add(E e) --

  • Java的类型擦除式泛型详解

    Java选择的泛型类型叫做类型擦除式泛型.什么是类型擦除式泛型呢?就是Java语言中的泛型只存在于程序源码之中,在编译后的字节码文件里,则全部泛型都会被替换为原来的原始类型(Raw Type),并且会在相应的地方插入强制转型的代码. 因此,对于运行期间的Java程序来说ArrayList< Integer>和ArrayList< String>其实是同一个类型.这也就是Java选择的泛型类型叫做类型擦除式泛型的原因. ArrayList<String> stringAr

  • Java语法关于泛型与类型擦除的分析

    泛型与类型擦除 泛型,JDK 1.5新特性,本质是参数化类型(Parametersized Type) 的应用,即所操作的数据类型被指定为一个参数.这种参数类型可用在: 类 接口 方法 的创建中, 分别称为: 泛型类 泛型接口 泛型方法 在Java还没有泛型的版本时.只能通过: Object 是所有类型的父类 类型强制转换 两个特性协作实现类型泛化.例如,在哈希表的存取中,JDK 1.5之前使用HashMap的get() 方法,返回值就是个Object.由于Java语言里面所有的类型都维承于ja

  • Java泛型之类型擦除实例详解

    目录 前言 泛型是什么? 泛型的定义和使用 泛型类 泛型方法 泛型类与泛型方法的共存现象 泛型接口 通配符 ? 无限定通配符 <?> <? extends T> 类型擦除 类型擦除带来的局限性 泛型中值得注意的地方 Java 不能创建具体类型的泛型数组 泛型,并不神奇 总结 前言 泛型,一个孤独的守门者. 大家可能会有疑问,我为什么叫做泛型是一个守门者.这其实是我个人的看法而已,我的意思是说泛型没有其看起来那么深不可测,它并不神秘与神奇.泛型是 Java 中一个很小巧的概念,但同时

  • 详解Java泛型中类型擦除问题的解决方法

    以前就了解过Java泛型的实现是不完整的,最近在做一些代码重构的时候遇到一些Java泛型类型擦除的问题,简单的来说,Java泛型中所指定的类型在编译时会将其去除,因此List 和 List 在编译成字节码的时候实际上是一样的.因此java泛型只能做到编译期检查的功能,运行期间就不能保证类型安全.我最近遇到的一个问题如下: 假设有两个bean类 /** Test. */ @Data @NoArgsConstructor @AllArgsConstructor public static class

  • 泛型的类型擦除后fastjson反序列化时如何还原详解

    目录 铺垫 错误写法1 错误写法2 正确写法 TypeReference 验证 扩展 铺垫 在前面的文章中,我们讲过Java中泛型的类型擦除,不过有小伙伴在后台留言提出了一个问题,带有泛型的实体的反序列化过程是如何实现的,今天我们就来看看这个问题. 我们选择fastjson来进行反序列化的测试,在测试前先定义一个实体类: @Data public class Foo<T> { private String val; private T obj; } 如果大家对泛型的类型擦除比较熟悉的话,就会知

  • 带大家认识Java语法之泛型与通配符

    目录 ️前面的话️ 1.泛型 1.1泛型的用法 1.1.1泛型的概念 1.1.2泛型类 1.1.3类型推导 1.2裸类型 1.3擦除机制 1.3.1关于泛型数组 1.3.2泛型的编译与擦除 1.4泛型的上界 1.4.1泛型的上界 1.4.2特殊的泛型上界 1.4.3泛型方法 1.4.4类型推导 2.通配符 2.1通配符的概念 2.2通配符的上界 2.3通配符的下界 总结 ️前面的话️ 本篇文章带大家认识Java语法——泛型与通配符,泛型和通配符是一个非常抽象的概念,简单来说,两者都可以将类型作为

  • java基础之泛型知识点总结

    一.什么是泛型?为什么要使用泛型? 泛型,即"参数化类型".一提到参数,最熟悉的就是定义方法时有形参,然后调用此方法时传递实参.那么参数化类型怎么理解呢?顾名思义,就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),然后在使用/调用时传入具体的类型(类型实参). 泛型的本质是为了参数化类型(在不创建新的类型的情况下,通过泛型指定的不同类型来控制形参具体限制的类型).也就是说在泛型使用过程中,操作的数据类型被指定为一个参数,这种参数

  • Java不能真正泛型的原因是什么?

    目录 简单来回顾一下类型擦除,看下面这段代码. 为什么 Java 不能实现真正意义上的泛型呢?背后的原因是什么? 第一,兼容性 第二,不是"实现不了" 总结 简单来回顾一下类型擦除,看下面这段代码. public class Cmower { public static void method(ArrayList<String> list) { System.out.println("Arraylist<String> list"); } p

  • 详解java 中泛型中的类型擦除和桥方法

    在Java中,泛型的引入是为了在编译时提供强类型检查和支持泛型编程.为了实现泛型,Java编译器应用类型擦除实现: 1.  用类型参数(type parameters)的限定(如果没有就用Object)替换泛型类型中的所有类型参数. 2.  需要保持类型安全的时候插入类型转换(隐含插入) 3.  在extened 泛型类型中生成桥方法来保证多态性 类型擦除确保不会为已参数化了的类型(paramterized types)产生新类,这样泛型能保证没有运行时的负载. 泛型类型擦除 在类型擦除过程中,

随机推荐