一 、Java泛型的原理?什么是泛型擦除机制?
Java的泛型是JDK5新引入的特性,为了向下兼容,虚拟机其实是不支持泛型,所以Java实现的是一种伪泛型机制,也就是说Java在编译期擦除了所有的泛型信息,这样Java就不需要产生新的类型到字节码,所有的泛型类型最终都是一种原始类型,在Java运行时根本就不存在泛型信息。
二、Java编译器具体是如何擦除泛型的
- 检查泛型类型,获取目标类型
- 擦除类型变量,并替换为限定类型
如果泛型类型的类型变量没有限定(<T>),则用Object作为原始类型
如果有限定(<T extends XClass>),则用XClass作为原始类型
如果有多个限定(T extends XClass1&XClass2),则使用第一个边界XClass1作为原始类
- 在必要时插入类型转换以保持类型安全
- 生成桥方法以在扩展时保持多态性
三、使用泛型以及泛型擦除带来的影响(副作用)
- 泛型类型变量不能使用基本数据类型
比如没有ArrayList<int>,只有ArrayList<Integer>.当类型擦除后,
ArrayList的原始类中的类型变量(T)替换成Object,但Object类型不能
存放int值 -
不能使用instanceof 运算符
因为擦除后,ArrayList<String>只剩下原始类型,泛型信息String
不存在了,所有没法使用instanceof
instenceof1.png -
泛型在静态方法和静态类中的问题
因为泛型类中的泛型参数的实例化是在定义泛型类型对象
(比如ArrayList<Integer>)的时候指定的,而静态成员是不需要使用
对象来调用的,所有对象都没创建,如何确定这个泛型参数是什么
静态类型.png - 泛型类型中的方法冲突
因为擦除后两个equals方法变成一样的了
@Override
public boolean equals(T t) {
return super.equals(t);
}
@Override
public boolean equals(Object o) {
return super.equals(o);
}
-
没法创建泛型实例
因为类型不确定
泛型不能创建实例.png - 没有泛型数组
因为数组是协变,擦除后就没法满足数组协变的原则
逆变与协变
-
可变性是以一种类型安全的方式,将一个对象当做另一个对象来使用。如果不能将一个类型替换为另一个类型,那么这个类型就称之为:不变量。
协变和逆变是两个相互对立的概念: - 协变:如果某个返回的类型可以由其派生类型替换 那么这个类型就是支持协变的
-
逆变:如果某个参数类型可以由其基类替换,那么这个类型就是支持逆变的
泛型数组不能创建.png
网友评论