转自http://www.oseye.net/user/kevin/blog/167
类型擦除是Java中泛型的实现方式。为了保证泛型引入之前的字节代码在不经过任何修改的情况下酒可以在新版的的虚拟机上运行,所以泛型是在编译器这个层次来实现的,这就保持了Java平台的兼容性。在Java源代码中声明的泛型类型信息,在编译过程中会被擦除,只保留不带类型参数的形式。
经过类型擦除之后,包含泛型类型的代码被转换成不包含泛型类型的代码,相当于回到了泛型被引入之前的形式,Java虚拟机在运行字节代码时并不知道泛型类型的存在。虽然为了反射API的需要,在Java字节代码中包含了与泛型类型相关的信息,但这些信息在字节代码执行时是不被使用的。
编译器和虚拟机所能区分的类型是不同的:对于编译器来说,List<String>和List<Integer>是不同的类型;而对于虚拟机来说,这两者的类型都是List。在运行时可用的类型被称为可具体化类型(reifiable type)。在Java中可具体化类型包括非泛型类型、所有实际类型都是无界通配符的参数化类型、原始类型、基本类型、元素类型为可具体化类型的数据类型、以及福类型和自身都是可具体化类型的嵌套类型。如String、List<?>、List、int、String[]和MyClass<?>.Inner都是可具体化类型。
类型的实现方式虽然是兼容的,但这种兼容性,对于Java这样一个广泛使用的语言来说相当重要,但也带来了泛型在设计上的不自然和使用方式上的局限。
基本类型
类型参数可以指定的类型不包括基本类型,因此没有"MyClass<double>",只有"MyClass<Double>"。这是由于当实施擦除时,Object不能直接存储double类型的值。
静态类型
不能在静态成员中使用类的类型变量,如:
- public class MyClass<T>{
- public static T getValue(){}
- }
这是由于类型变量实际代表的类型要到创建对象时才会给出,而静态方法只要类加载之后就可以调用了。但可以这样
- public class MyClass{
- public static <T> T getValue(){}
- }
或
- public class MyClass<T>{
- public static <M> M getValue(){}
- }
class对象
List<String>和List<Integer>类型对于虚拟机来说是相同的,表示的都是List接口。所以无法通过类似"List<String>.class"的形式获取参数化类型的类对象字面量,而只能使用List.class。在运行时并不存在List<String>类型,只有List类型。
instanceof检查
在Java 6中,可以这样使用instanceof检查,但实际上不包括泛型部分的检查,而且在编译时会产生两条警告信息。
- ArrayList<Integer> myIntList=new ArrayList<Integer>();
- System.out.println(myIntList instanceof ArrayList<Integer>);
- System.out.println(myIntList instanceof ArrayList<String>);
但在Java 7中,除了实际类型是无界通配符外的泛型都不能使用instanceof操作符,如"myIntList instanceof ArrayList<?>"是合法的,而"myIntList instanceof ArrayList<Integer>)"是非法的,编译不通过。因为这两种参数化类型在类型擦除之后都是ArrayList,如果允许这种行为,开发人员容易产生误解。
分享到:
相关推荐
Java中的泛型,在运行时刻其具体类型是被擦除的,这样我们就不能用new T(),instanceof等关操作,特别是对泛型类型的类的实例化问题,在此根据《Thinking in Java》中所讲的对类型擦除所带来问题的三种解决方案,比较...
NULL 博文链接:https://hyzhaolt.iteye.com/blog/443661
解析Java泛型的类型擦除.pdf
详细的介绍了Java是伪泛型的原因,介绍了类型擦除的内容等。
JAVA泛型 28 类型擦除 28 实例分析 29 通配符与上下界 30 类型系统 31 开发自己的泛型类 32 最佳实践 32 参考资料 33 目录 3 JAVA注解 34 使用注解 34 开发注解 35 处理注解 35 实例分析 38 参考资料 39 JAVA反射与...
本文主要介绍了Java泛型的使用以及类型擦除相关的问题。具有很好的参考价值。下面跟着小编一起来看下吧
Java 泛型最全指南(定义和使用+继承泛型类/实现泛型接口+泛型的边界+通配符+类型擦除)
“编译器会进行泛型擦除”是一个常识了(好吧,实际擦除的是参数和自变量的类型)。这个过程由“类型擦除”实现。但是并非像许多开发者认为的那样,在 <..> 符号内的东西都被擦除了。看下面这段代码: public ...
主要介绍了详解java 中泛型中的类型擦除和桥方法的相关资料,需要的朋友可以参考下
2. 类型擦除:Java泛型在编译时实现类型安全检查,但在运行时会将泛型类型的信息擦除,转换为原始类型。这是为了保持与Java早期版本的兼容性,同时减少运行时的开销。例如,List在运行时会被擦除为List。 3. 上限和...
环境:Windows XP Professional、JDK 1.6、Ant 1.7 说明:Java泛型的动机是为解决类型转换在编译时不报错的问题。另外由于“范型编程”(Generic Programming)的推广,于是2004年JDK 5.0引用范型标准。本例子说明...
学习和理解Java泛型的基本概念和语法; 实际项目中需要使用泛型来增加类型安全性和重用性的开发任务。 目标: 本代码资源的目标是帮助读者理解泛型的用法和优势,并通过实际的示例代码加深对泛型的掌握。读者可以...
- 泛型擦除前的例子把这段Java代码编译成Class文件,然后再用字节码反编译后,將会发现泛型都不见了,又变回了Java泛型出现之前的写法,泛型类型都变回了原
源代码中使用的泛型,在经过编辑后,代码中就看不到泛型,也就是所谓的泛型擦除 泛型擦除不是泛型丢失了,而是在编译后的字节码文件中使用单独的标识来存储泛型了。 为什么会出现泛型擦除,主要是为了编译器的...
主要介绍了JAVA泛型的继承和实现、擦除原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
6.2. 擦除和翻译(Erasure and Translation) 6.3. 在老代码中使用泛型代码 7. 要点(The Fine Print) 7.1. 一个泛型类被其所有调用共享 7.2. 转型和instanceof 7.3. 数组Arrays 8. Class Literals as Run-time Type ...
主要介绍了Java编程探索之泛型擦除实例解析,具有一定参考价值,需要的朋友可以了解下。
泛型在java中有很重要的地位,在面向对象编程及各种设计模式中有非常广泛的应用。泛型是参数化类型的应用,操作的数据类型不限定于特定类型,可以根据实际需要设置不同的数据类型,以实现代码复用。下面小编来简单讲...
在Java SE1.5之前,没有泛型的情况的下,通过对类型Object的引用来实现参数的“任意化”,“任意化”带来的缺点是要做显式的强制类型转换,而这种转换是要求开发者对实际参数类型可以预知的情况下进行的。...
本文我们将从零开始来看一下Java泛型的设计,将会涉及到通配符处理,以及让人苦恼的类型擦除。 泛型基础 泛型类 我们首先定义一个简单的Box类: public class Box { private String object; ...