泛型擦除与转换
主讲教师:王少华 QQ群:483773664
学习目标:
- 掌握泛型擦除的含义
- 理解泛型转换的规则
一、泛型擦除
(一)什么泛型擦除
Java中的泛型基本上都是在编译器这个层次来实现的。在生成的Java字节码中是不包含泛型中的类型信息的。也就是说虚拟机中没有泛型,只有普通类和普通方法
使用泛型的时候加上的类型参数,会在编译器在编译的时候去掉。这个过程就称为类型擦除。
类型擦除的主要过程如下:
1.将所有的泛型参数用其最左边界(最顶级的父类型)类型替换。
2.移除所有的类型参数。
如在代码中定义的List<object>和List<String>等类型,在编译后都会编程List。JVM看到的只是List,而由泛型附加的类型信息对JVM来说是不可见的。
1 2 3 4 5 6 7 8 9 |
|
在这个例子中,我们定义了两个ArrayList数组,不过一个是ArrayList<String>泛型类型,只能存储字符串。一个是ArrayList<Integer>泛型类型,只能存储整形。最后,我们通过arrayList1对象和arrayList2对象的getClass方法获取它们的类的信息,最后发现结果为true。说明泛型类型String和Integer都被擦除掉了,只剩下了原始类型。
(二)类型擦除带来的问题
正是由于类型擦除的隐蔽存在,直接导致了众多的泛型灵异问题。
1、不能通过泛型类的实例区分方法签名,以实现方法重载
2、不能catch中使用泛型
3、泛型类的静态变量是共享的
1 2 3 4 5 6 7 8 9 10 |
|
(三)、避免泛型擦除
1、创建泛型对象时请指明类型
比如
1 |
|
改成
1 |
|
2、下面二种写法的区别
1 2 |
|
new ArrayList()只是在内存中开辟一个存储空间,可以存储任何的类型对象。而真正涉及类型检查的是它的引用,因为我们是使用它引用arrayList1 来调用它的方法,比如说调用add()方法。所以arrayList1引用能完成泛型类型的检查。而引用arrayList2没有使用泛型,所以不行
二、泛型转换
(一)有泛型转无泛型
当把一个具有泛型信息的对象赋给另一个没有泛型信息的变量时,则所有在尖括号之间的类型信息都被扔掉了。
比如说,一个List<String>类型被转换为List,则该List对集合元素的类型检查变成了类型变量的上限(Object)
1 2 3 4 5 6 7 8 9 10 11 12 |
|
(二)泛型A不能转泛型B
跟王老师学泛型(八):泛型擦除与转换