zoukankan      html  css  js  c++  java
  • Java泛型基础知识笔记:泛型定义模板的意义、泛型的擦拭法、extends和super通配符区别、PESC原则

    一、什么是泛型

    1、ArrayList 误转型的案例。为了解决新的问题,我们必须把ArrayList变成一种模板:ArrayList<T>,代码如下:

    public class ArrayList<T> {
        private T[] array;
        private int size;
        public void add(T e) {...}
        public void remove(int index) {...}
        public T get(int index) {...}
    }

      T可以是任何class。这样我们就实现了:编写一次模版,可以创建任意类型的ArrayList

    // 创建可以存储String的ArrayList:
    ArrayList<String> strList = new ArrayList<String>();
    // 创建可以存储Float的ArrayList:
    ArrayList<Float> floatList = new ArrayList<Float>();
    // 创建可以存储Person的ArrayList:
    ArrayList<Person> personList = new ArrayList<Person>();

    2、因此,泛型就是定义一种模板,例如ArrayList<T>,然后在代码中为用到的类创建对应的ArrayList<类型>,由编译器针对类型作检查。

      这样既实现了编写一次,万能匹配,又通过编译器保证了类型安全:这就是泛型。

    3、小结:

      泛型就是编写模板代码来适应任意类型

      泛型的好处是使用时不必对类型进行强制转换,它通过编译器对类型进行检查;

      注意泛型的继承关系:可以把ArrayList<Integer>向上转型为List<Integer>T不能变!),但不能把ArrayList<Integer>向上转型为ArrayList<Number>T不能变成父类)。(注重 T 不能变)

    二、使用泛型

    1、使用泛型时,把泛型参数<T>替换为需要的class类型,例如:ArrayList<String>ArrayList<Number>等;

    2、可以省略编译器能自动推断出的类型,例如:List<String> list = new ArrayList<>();

    3、不指定泛型参数类型时,编译器会给出警告,且只能将<T>视为Object类型;

    4、可以在接口中定义泛型类型,实现此接口的类必须实现正确的泛型类型。

    三、泛型的擦拭法

    1、泛型是一种类似”模板代码“的技术,不同语言的泛型实现方式不一定相同。Java语言的泛型实现方式是擦拭法(Type Erasure)。所谓擦拭法是指,虚拟机对泛型其实一无所知,所有的工作都是编译器做的。

      Java的泛型是由编译器在编译时实行的,编译器内部永远把所有类型T视为Object处理,但是,在需要转型的时候,编译器会根据T的类型自动为我们实行安全地强制转型。

    2、Java的泛型是采用擦拭法实现的;擦拭法决定了泛型<T> 的局限性

    • 不能是基本类型,例如:int
    • 不能获取带泛型类型的Class,例如:Pair<String>.class
    • 不能判断带泛型类型的类型,例如:x instanceof Pair<String>
    • 不能实例化T类型,例如:new T()

    3、泛型方法要防止重复定义方法,例如:public boolean equals(T obj)

    4、子类可以获取父类的泛型类型<T>

    四、泛型的extends通配符和super通配符

    1、使用类似<? extends Number>通配符作为方法参数时表示:

    • 方法内部可以调用获取Number引用的方法,例如:Number n = obj.getFirst();

    • 方法内部无法调用传入Number引用的方法(null除外),例如:obj.setFirst(Number n);

      即一句话总结:使用extends通配符表示可以读,不能写

    2、使用类似<T extends Number>定义泛型类时表示:限定子类

    • 泛型类型限定为Number以及Number的子类。

    3、使用类似<? super Integer>通配符作为方法参数时表示:

    • 方法内部可以调用传入Integer引用的方法,例如:obj.setFirst(Integer n);

    • 方法内部无法调用获取Integer引用的方法(Object除外),例如:Integer n = obj.getFirst();

      即使用super通配符表示只能写不能读

    4、使用extendssuper通配符要遵循PECS原则。

    5、无限定通配符<?>很少使用,可以用<T>替换,同时它是所有<T>类型的超类。

    6、PECS原则 —— 何时使用extends,何时使用super

      为了便于记忆,我们可以用PECS原则:Producer Extends Consumer Super。

      即:如果需要返回T,它是生产者(Producer),要使用extends通配符;如果需要写入T,它是消费者(Consumer),要使用super通配符。

  • 相关阅读:
    【NOIP2007】守望者的逃离
    20200321(ABC)题解 by 马鸿儒 孙晨曦
    20200320(ABC)题解 by 王一帆
    20200319(ABC)题解 by 王一帆 梁延杰 丁智辰
    20200314(ABC)题解 by 董国梁 蒋丽君 章思航
    20200309(ABC)题解 by 梁延杰
    20200307(DEF)题解 by 孙晨曦
    20200306(ABC)题解 by 孙晨曦
    20200305(DEF)题解 by 孙晨曦
    20200303(ABC)题解 by 王锐,董国梁
  • 原文地址:https://www.cnblogs.com/goloving/p/14813577.html
Copyright © 2011-2022 走看看