java进阶-泛型

一、何为泛型?

    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 = new ArrayList<>();

           list.add(1);//编译器报错

           list.add("test");

           String element = list.get(0);//不用强制类型转化

    2.2 代码复用

        比如实现数字排序的算法sort();

        定义 public static void sort(T[] a, Comparator c),所有实现了Comparator的接口的类型都可以进          行排序算法,如果没有泛型,则需要针对int,double,float等各自实现一套sort算法

三、泛型的使用

    3.1 泛型类、接口一样

        public class A {};

        punlic classA {}

    3.2 泛型方法(返回类型之前必须有<>),可以定在普通类也可定义在泛型类,但是在泛型类中定义时各自维护各自的泛型T

        public void set(T t);

        public void set(T t);

        public T get();

四、通配符 ? 灵活转型(如网络架构Rxjava)

    4.1 非限定通配符 ?;     A a  等价于 A 既不能读也不能写,但作为方法入参可进行类型安全检验,另外作为引用时只进行Object相关操作也可,最典型的是Class clz;

    4.2 上界通配符;  只能读不能存(原因下面的继承关系中讲)

    4.3 下界通配符;  只能存且存T或者T的子类,不能读T,但是能读返回Object

五、泛型与继承、多态

    5.1 继承:

        class A{};  class B extends A 或者 class B extends A

        class C extends D{}, class D extends E{};  List 与 List没有继承关系; 但是List是ArrayList的父类,只要泛型不变,则类的继承关系不变;

        List -> List -> (List 和List)  父类关系成立(左侧是父类) ;

        List list = new ArrayList(); 或者  List list = new ArrayList();正因为这层继承关系,所以list引用可执行D的容器,也可指向C的容器,对于JVM来说,不清楚你最后可能指向的是哪个容器,所以禁止 上界通配符定义的变量能存放数据,否则会涉及类型安全问题。


        List -> List -> (List和List

六、JVM如何实现泛型?

    6.1 编译前进行类型检查,编译后进行类型擦除,擦除的泛型信息保存在常量池中,通过反射可获取;

        List listC = new ArrayList<>();  List listD = new ArrayList<>();  listC.getClass 与 listD.getClass是一样的,都是List;这就是类型擦除;

    6.2 类型擦除原则如下:

           没有限定则Object

           有则用限定类型

           桥方法维护多态性

           擦除了但依旧可以通过反射获得泛型类,类常量池有保存泛型类信息

    6.3 泛型后遗症如下:

        1、不能实例化类型变量 new T(),可以通过反射获得实例;

        2、static T t  static void set(T t)静态属性或者方法里不能引用类型变量,对象创建的时候才知道类型,static属于类,先执行,此时还不知道具体是什么类型;静态泛型方法可以static void set(T t)

       3、基本类型不支持作为实参,List list 不行,List 可以

       4、instanceof不支持(泛型擦除导致,没有了类型信息)  如果是A  这个能用instanceof吗?

       5、泛型数组不支持

        A extents B  A[] 的分类是 B[]  数组的协变

        类型擦除后不能支持协变了

       6、泛型类不能extends Exception/Throwable,也不能catch泛型类对象,但是可以catch exception然后throws出来即可

七、总结:

    泛型设计初衷就是为了灵活的实现类型转型,这样设计和开发通用功能模块时可对用户透明,解耦且通用,强行记住上下界规则PECS(Product extends Consumer super),上不存下不取或者上只读下只写。

  

你可能感兴趣的:(java进阶-泛型)