Java 泛型擦除详解
本文主要讲解关于Java 泛型擦除相关内容,让我们来一起学习下吧!
1、什么是泛型擦除
泛型信息只存在于代码编译阶段,在进入JVM之前,与泛型相关的信息会被擦除掉。
2、举例
- 真相就是泛型在jvm都会被替换为Object
- List list = new ArrayList< String>();左边编译时声明的静态类型,右边是运行时实现的实际类型
- 那么list.add时则不会限制类型
public static void main(String[] args) { List list = new ArrayList(); List listString = new ArrayList<String>(); List listInteger = new ArrayList<Integer>(); list.add(1); listString.add(123); listInteger.add("kentwang"); System.out.println(list.size()+""+listString.size()+""+listInteger.size()+""); System.out.println(list.size()+""+listInteger.get(0)); }
- 之所以get返回值时Object类型时因为在ArrayList 已经将泛型E擦除了,全都变为了Object,即使后边有类型转换,或者运行而不会报错。
3、会有啥问题
3.1、强制类型转换会有编译器无法检测的问题。
List listInteger = new ArrayList<Integer>(); listInteger.add("KENT"); System.out.println(""+(int)listInteger.get(0));
- 这个不会报错,我申明是list,实现是ArrayList< Integer>,编译时静态类型是List。add可以加任何类型。运行时是ArrayList< Integer>实际类型,我强转为(Integer)应该的嘛,但是会出错
3.2、引用传递问题
- 上面的问题中,我们已经说过了
T
将在后期被转义成Object
,那我们对引用也进行一个转化,是否行得通呢?
//都会报错 List<String> listObject = new ArrayList<Object>(); List<Object> listObject = new ArrayList<String>();
假设说我们的第一种方案是正确的,那么其实就是将一堆Object
数据存入,然后再由上面所说的强制转化一般,转化成String
类型,听起来完全ok,因为在List
中本来存储数据的方式就是Object
。但其实是会出现ClassCastException
的问题,因为Object
是万物的基类,但是强转是为子类向父类准备的措施。
再来假设说我们的第二种方案是正确的,这个时候,根据上方的数据String
存入,但是有什么意义存在呢?最后都还是要成Object
的,你还不如就直接是Object
。
4、解决方案
- 用泛型通配符
- 强制类型转为的问题和引用传递问题,在编译期就给解决了
- 看之前的《Java 泛型通配符详解》文章
5、要用Java泛型擦除的原因
- java泛型是伪泛型,泛型擦除就是代码在编译阶段,与泛型相关的信息会被清除。
- 泛型本质上是给编译器检查用的,并不改变运行时的类型。
- java5新增泛型,如果用真泛型
- 修改 JVM 源代码,让 JVM 能正确的的读取和校验泛型信息
- 为了兼容老程序,需为原本不支持泛型的 API 平行添加一套泛型 API(主要是容器类型)。
- java5之下的库A,要改代码,假设B项目升级到Java5,那么,A项目必要时要升级Java5,并且改代码。
- 因为在 Java 中不支持高版本的 Java 编译生成的 class 文件在低版本的 JRE 上运行,如果尝试这么做,就会得到 UnsupportedClassVersionError 错误。如下图所示:
ArrayList<User> users = new ArrayList<>(); ArrayList<Dog> dogs = new ArrayList<>(); System.out.println(users.getClass() == dogs.getClass()); // 输出 true
- 思来想去怎么让老版本不该,新版本改呢?我不增加API,在编译器检查时限制你,然后在编译器里擦除变为Object,再jvm里面新老版本就一样了。
以上就是关于Java 泛型擦除 相关的全部内容,希望对你有帮助。欢迎持续关注潘子夜个人博客(www.frpkj.com),学习愉快哦!