美文网首页重走安卓进阶路
重走安卓进阶路——泛型

重走安卓进阶路——泛型

作者: 小呀么小黄鸡 | 来源:发表于2020-03-10 10:28 被阅读0次

    ps.原来的标题

    • 为什么我们需要泛型?
    • 泛型类、泛型接口和泛型方法(泛型类和泛型接口的定义与泛型方法辨析);
    • 如何限定类型变量?
    • 泛型使用中的约束和局限性;
    • 泛型类型能继承吗?
    • 泛型中通配符类型;
    • 虚拟机是如何实现泛型的?

    为什么需要泛型

    1. 泛型扩展了类、接口、方法的适用范围
    2. 提前生命可使用的类型,在编译期提供提醒
    3. 避免List使用时的强制类型转换

    如何使用泛型

    1. 泛型类
      在类名后加上例如“<K>”这样的泛型来声明泛型变量,在类体重再添加正式的范型变量/方法后即可使用。

    注意:

    • 一般有T、E、K、V等字母可表示泛型,约定俗成
    • 也可以有多个,用逗号间隔,如“<K,V>”
    1. 泛型接口
      声明与泛型类无异, 重点在实现。
      实现有两种方法:
      <1> 用泛型类来实现泛型接口,仍返回泛型
      <2>直接用确定的类型来替换字母泛型,返回的也是指定类型

    2. 泛型方法
      可完全独立,可以不在泛型接口,泛型类中
      例:
      此处的“<T>”是泛型方法的明确标志

    public <T> T genericMethod (T ...a){
      return a[a.length/2];
    }
    

    注意:

    • 不是在泛型类里的就是泛型方法
    • 泛型类是使用泛型方法同样要有标志<T>???
    • 在泛型类里的泛型方法完全可以和类中定义的泛型不一样
    • 泛型类上声明的泛型只影响普通方法,泛型类中的泛型方法声明的泛型与泛型类上声明的泛型无关

    限定类型变量的应用场景

    extends 派生/继承 类或接口
    需要在泛型应用过程中要求该泛型拥有某种方法或遵循某种规则

    注意:
    限定混用类与接口时,类必须写在最前面,且只能有一个(单继承)
    <T extends ArrayList & Comparable>

    约束与局限性

    1. 不能实例化类型变量
      this.data = new T();
    2. 静态域或者方法不能引用类型变量
      因为静态在声明、使用时,泛型很可能还未声明
      除非该静态方法本身就是泛型方法
    3. 如果泛型要使用基本类型,只能用其包装类,因为基本类型不是对象
    4. 范型变量不能使用instance of 方法
    5. 注入不同类型后的泛型类,使用getClass()只能获取其原生类型而不是泛型
      6 Model<Double> m = new Model<>();可行
      Model<Double>[] ms = new Model<Double>[10];不可行
    6. 泛型类不能派生自Throwable,
      如果泛型方法声明T派生自Throwable,不能通过捕获(catch)泛型类对象T,但可通过捕获(catch)Throwable类型,再直接抛出(throws T)

    泛型类型的继承规则

    1. 约束与局限性中的第五条可知,存在Class A, Class B extends A
      Model为范行为,Model<A>与Model<B>没有关系,即不允许Model<A> a = new Model<B>();
    2. 要区别于反省类之间的派生
      如 ModelE<T> extends Model<T>
      允许 Model<T> b = new ModelE<>();
      直接例子就是List和ArrayList
    3. 若存在public <T> void set(Model<A> m){}方法
      Model<A> a = new Model<>();
      Model<B> b = new Model<>();
      set(a);//可行
      set(b);//报错
      这一条引出了泛型中通配符的使用

    通配符

    泛型类型的继承规则的第3条中的public <T> void set(Model<A> m){}修改为
    public <T> void set(Model<? extends A> m){}即可成立

    注意:通配符用于方法或变量,而不能用于泛型类上的泛型声明
    <? extends Model>限定了上界,意味着能传Model及其子类
    <? super Model>限定了下界,意味着能穿Model及父类

    因此对<? extends Model>进行getData(),只返回Model类型,因为只知上界;
    对<? extends Model>进行setData(),无法传入其子类,因为不知下界;
    对<? super Model>进行getData()返回Object,因为最上界已限定;
    对<? super Model>进行setData()可传入其子类,因为已知上界。

    虚拟机实现泛型

    泛型擦除,jdk会用代码中提到过的最接近的类型来直接替代泛型类型,或插入强制转型的代码。
    可以通过方法重载的失效来证明这一点

    相关文章

      网友评论

        本文标题:重走安卓进阶路——泛型

        本文链接:https://www.haomeiwen.com/subject/omzydhtx.html