1.获取值的时候需要进行类型转换
2.插入的时候无法约束预期类型
如果向集合中添加了非预期的类型,编译时我们不会受到任何错误提示,当程序运行时却会爆出异常。针对以上问题引入了泛型。
1。什么是泛型泛型就是将类型参数化,在使用的时候将要使用的类型传入就变成类型实参,这样突破了通过继承来实现的通用程序代码的设计。
他的主要目的就是:编译时期类型检查,增强安全性和可读性,并且自动进行类型强制转换,避免运行时才爆出类型匹配错误。只要不适用这个原则一律报错
根据泛型使用地方可以分为
a.可以标记在接口上,叫泛型接口
b.可以标记在类上,叫泛型类
c可以标记在方法上,被称为泛型方法
这是一个普通方法,请知悉
2.泛型限定(类型限定)分为T extends Class( T super Classs)前者在使用时只能传入Class的子类,后者只能传入Class的父类
这些限定可以使用在泛型类也可以泛型方法上
3.泛型擦除(擦除类型变量,替换为限定类型)java是伪泛型,在编译时期擦除所有的泛型信息(类型变量),为限定类型,这样的话就不需要引入新的类型到字节码,在java运行时根本不存在泛型信息。在调用时会进行强制类型转换
编译器如何擦除呢?
1.检查泛型类型,获取目标类型
2.擦除类型变量,替换限定类型
如果T没有被限定,就会被擦除成Object
如果T extends xClass 就会被擦除成xClass
3.在必要时插入类型转换保证类型安全
4.生成桥方法以在扩展时保持多态性
4.突破泛型约束
类型变量会在编译时期,被擦除掉,被擦除成原始类型,因此可以通过反射的方法来进行
以下几点请特别注意1.泛型只适合引用类型,基本类型不可以使用
2.不能使用InstanceOf 运算符
ArrayList
s1 instanceOf ArrayList
3.泛型在静态类和静态方法中的问题
泛型类型是在创建泛型对象的时候指定的,所以类中的静态变量和静态方法使用了泛型,就不知道该泛型应该是哪个类型了,所以会报错
而静态泛型方法的指定类型实在调用的时候确定的,因此没问题
4.泛型擦除后的方法可能跟重写的方法冲突
5.没办法创建泛型实例,即 T t=new T()
6.没有泛型数组
Plate[] appluPlates = new Plate[10]不允许
Plat
class B extengs A
class C extends B
Plate 与Plate, Plate 与Plate
但是 下面的情况有继承关系
为了解决刚才紫色字体的问题,也想让泛型中可以使用类型多态,才有了通配符的概念,比如
现在我们有继承关系的类
则会产生这种情况:
? extends X 表示类型的上界,类型参数是X的子类
主要用于安全地访问数据,可以访问X及其子类型,并且不能写入非null的数据
? super X 表示类型的下界,类型参数是X的超类
总结:主要用于安全地写入数据,可以写入X及其子类型。
无限定的通配符 ?表示对类型没有什么限制,可以把?看成所有类型的父类,如Pair< ?>;
遵守PECS原则 生产者只能get 消费者只能set
擦除法所谓的擦除,仅仅是对方法的Code属性中的字节码进行擦除,实际上元数据中还是保留了泛型信息,这也是我们能通过反射手段取得参数化类型的根本依据



