深入理解Java虚拟机 - 泛型与类型擦除 港控/mmm° 2022-06-03 07:44 112阅读 0赞 泛型是JDK 1.5的一项新增特性,它的本质是参数化类型(Parametersized Type)的应用,也就是说所操作的数据类型被指定为一个参数。 这种参数类型可以用在类、 接口和方法的创建中,分别称为泛型类、 泛型接口和泛型方法。 Java语言中的泛型只在程序源码中存在,在编译后的字节码文件中,就已经替换为原来的原生类型了,并且在相应的地方插入了强制转换代码,因此,对于运行期的Java语言来说,ArrayList<int>与ArrayList<String>就是同一个类,所以泛型技术实际上是Java语言的一颗语法糖,Java语言中的泛型实现方法称为类型擦除,基于这种方法实现的泛型称为伪泛型。 看下面一段简单的Java泛型的例子 public static void main(String[] args) { Map<String, String> map = new HashMap<String, String>(); map.put("hello", "你好"); map.put("how are you?", "天气不错"); System.out.println(map.get("hello")); System.out.println(map.get("how are you?")); } 把这段Java代码编译成Class文件,然后再用字节码反编译工具进行反编译后,将会发现泛型都不见了,程序又变回了Java泛型出现之前的写法,泛型类型都变回了原生类型,如下所示。 public static void main(String[] args) { Map map = new HashMap(); map.put("hello", "你好"); map.put("how are you?", "天气不错"); System.out.println((String)map.get("hello")); System.out.println((String)map.get("how are you?")); } ### 类型擦除带来的问题 ### 正是由于类型擦除的隐蔽存在,直接导致了众多的泛型灵异问题,如当泛型遇见重载 public class GenericTypes { public static void method(List<String> list) { System.out.println("List<String> list"); } public static void method(List<Integer> list) { System.out.println("List<Integer> list"); } } 这段代码将无法进行编译,因为参数List<Integer>和List<String>编译之后都被擦除了,变成了一样的原生类型List<E>,擦除动作导致这两种方法的特征签名变得一模一样。初步看来,无法重载的原因已经找到了,但真的就是如此吗?只能说,泛型擦除成相同的原生类型只是无法重载的其中一部分原因,请再接着如下代码 public class GenericTypes { public static String method(List<String> list) { System.out.println("invoke method List<String> list"); return ""; } public static int method(List<Integer> list) { System.out.println("invoke method List<Integer> list"); return 1; } public static void main(String[] args) { method(new ArrayList<String>()); method(new ArrayList<Integer>()); } } 执行结果 invoke method List<String> list invoke method List<Integer> list 方法重载要求方法具备不同的特征签名,返回值并不包含在方法的特征签名之中,所以返回值不参与重载选择,但是在 Class 文件格式之中,只要描述符不是完全一致的两个方法就可以共存。也就是说,两个方法如果有相同的名称和特征签名,但返回值不同,那它们也是可以合法地共存于一个 Class 文件中的。 由于 List<String>和 List<Integer>擦除后是同一个类型,我们只能添加两个并不需要实际使用到的返回值才能完成重载。 擦除法所谓的擦除,仅仅是对方法的 Code 属性中的字节码进行擦除,实际上元数据中还是保留了泛型信息,这也是我们能通过反射手段取得参数化类型的根本依据。 -------------------- 参考文献:[深入理解Java虚拟机][Java] 周志明 著 [Java]: http://itmyhome.com/java-virtual-machine/
相关 深入理解:Java中的泛型和类型擦除 在Java中,泛型和类型擦除是两个重要的概念。 1. 泛型(Generics) 泛型是在创建类、接口或者方法时,可以指定参数类型的一种机制。通过使用泛型,我们可以编写更灵活、 缺乏、安全感/ 2024年09月19日 08:42/ 0 赞/ 4 阅读
相关 Java泛型和类型擦除的深入理解 在Java编程中,泛型和类型擦除是两个重要的概念,它们分别对应于现代面向对象设计中的类型系统。 1. 泛型(Generics) - 在Java 5引入 - 主要用于类、接口、 刺骨的言语ヽ痛彻心扉/ 2024年09月17日 11:33/ 0 赞/ 14 阅读
相关 深入理解Java中的泛型:类型擦除示例 在Java中,泛型是一种编程技术,它允许你在创建类、接口或方法时,使用一个或者多个类型参数。但是,最终编译的代码中,这些类型参数会被"类型擦除"(Type Erasure),转 水深无声/ 2024年09月16日 06:03/ 0 赞/ 14 阅读
相关 Java泛型:理解类型擦除与安全边界 在Java编程中,泛型是一种强大的机制,用于创建可以存储任意类型的对象。然而,泛型在使用过程中存在一些关键概念和安全边界。 1. 类型擦除(Type Erasure): 一时失言乱红尘/ 2024年09月16日 06:03/ 0 赞/ 19 阅读
相关 深入理解Java泛型:类型擦除和约束 Java泛型是一种强大的工具,用于在编写代码时提供类型安全。下面我们将深入理解Java泛型中的类型擦除、约束以及它们的应用。 1. 类型擦除(Type Erasure) 淩亂°似流年/ 2024年09月13日 02:00/ 0 赞/ 20 阅读
相关 Java泛型:理解类型擦除问题 在Java编程中,泛型是一种强大的机制,用于创建可重用的模板类或方法。这些泛型通常包含类型参数,如<T>。 然而,尽管泛型提供了类型安全的优势,但在某些情况下,会遇到一个被称 àì夳堔傛蜴生んèń/ 2024年09月12日 18:27/ 0 赞/ 19 阅读
相关 深入理解 Java 泛型擦除机制 我们都知道 Java 中的泛型可以在编译期对类型检查,避免类型强制转化带来的问题,保证代码的健壮性。不同语言对泛型的支持也不一样,Java 中的泛型类型在编译期会擦除,下面一个 ╰+攻爆jí腚メ/ 2022年12月02日 00:52/ 0 赞/ 162 阅读
相关 【深入Java泛型】(2)java泛型-类型擦除 一、概述 Java泛型在使用过程有诸多的问题,如不存在List<String>.class, List<Integer>不能赋值给List<Number>(不 素颜马尾好姑娘i/ 2022年07月13日 04:08/ 0 赞/ 237 阅读
相关 深入理解Java虚拟机 - 泛型与类型擦除 泛型是JDK 1.5的一项新增特性,它的本质是参数化类型(Parametersized Type)的应用,也就是说所操作的数据类型被指定为一个参数。 这种参数类型可以用在类、 港控/mmm°/ 2022年06月03日 07:44/ 0 赞/ 113 阅读
还没有评论,来说两句吧...