一、何为泛型?
jdk1.5之后引入泛型概念,可定义泛型类、接口、方法,且编译期会将泛型擦除,向下兼容;
二、泛型的优点?
2.1 编辑代码时保证类型安全,且省去强制类型转化
1.5之前代码:
List list = new ArrayList();
list.add(1);
list.add("test");
String element = (String)list.get(0);//编译器会报错
element = (String) list.get(1); //强制类型转化
1.5引入泛型之后:
List
list.add(1);//编译器报错
list.add("test");
String element = list.get(0);//不用强制类型转化
2.2 代码复用
比如实现数字排序的算法sort();
定义 public static
三、泛型的使用
3.1 泛型类、接口一样
public class A
punlic classA
3.2 泛型方法(返回类型之前必须有<>),可以定在普通类也可定义在泛型类,但是在泛型类中定义时各自维护各自的泛型T
public
public
public
四、通配符 ? 灵活转型(如网络架构Rxjava)
4.1 非限定通配符 ?; A> a 等价于 A extends Object> 既不能读也不能写,但作为方法入参可进行类型安全检验,另外作为引用时只进行Object相关操作也可,最典型的是Class> clz;
4.2 上界通配符 extends T>; 只能读不能存(原因下面的继承关系中讲)
4.3 下界通配符 super T>; 只能存且存T或者T的子类,不能读T,但是能读返回Object
五、泛型与继承、多态
5.1 继承:
class A
class C extends D{}, class D extends E{}; List
List> -> List extends D> -> (List
List extends D> list = new ArrayList
List> -> List super D> -> (List
六、JVM如何实现泛型?
6.1 编译前进行类型检查,编译后进行类型擦除,擦除的泛型信息保存在常量池中,通过反射可获取;
List
6.2 类型擦除原则如下:
没有限定则Object
有则用限定类型
桥方法维护多态性
擦除了但依旧可以通过反射获得泛型类,类常量池有保存泛型类信息
6.3 泛型后遗症如下:
1、不能实例化类型变量 new T(),可以通过反射获得实例;
2、static T t static void set(T t)静态属性或者方法里不能引用类型变量,对象创建的时候才知道类型,static属于类,先执行,此时还不知道具体是什么类型;静态泛型方法可以static
3、基本类型不支持作为实参,List
4、instanceof不支持(泛型擦除导致,没有了类型信息) 如果是A extents B> 这个能用instanceof吗?
5、泛型数组不支持
A extents B A[] 的分类是 B[] 数组的协变
类型擦除后不能支持协变了
6、泛型类不能extends Exception/Throwable,也不能catch泛型类对象,但是可以catch exception然后throws出来即可
七、总结:
泛型设计初衷就是为了灵活的实现类型转型,这样设计和开发通用功能模块时可对用户透明,解耦且通用,强行记住上下界规则PECS(Product extends Consumer super),上不存下不取或者上只读下只写。