Java 基礎:泛型

一、爲什麼要有泛型

  • 效率、成本
  • 減少樣板代碼的編寫

二、泛型的分類

  • 泛型類
  • 泛型方法

三、泛型的關鍵字

3.1 T

T 代表任意一個類型,可以爲任意字符串,一般爲:T、U、S、E、K、V。

  • T、U、S:任意類型
  • E:集合的元素類型
  • K、V:Map 的 key 和 value 類型

3.2 ?

? 是泛型通配符,代表任意一批類型。

四、泛型類、方法的定義

4.1 泛型類的定義

class AClass<T> ...
class AClass<T extends BClass> ... //沒有 T super BClass 這種寫法

<T> 在類名後聲明。在該類中,可以

  • 使用 T 作爲對象的類型聲明

    T a;

  • 使用 T 作爲泛型類型對象的類型參數

    List<T> list;

  • 使用 T 作爲方法返回類型前的聲明(所以泛型類中的泛型方法可以省去返回類型前的 )

    見泛型方法的定義

4.2 泛型方法的定義

public <T> void ...

<T> 在方法返回類型前聲明。在該方法中,可以

  • 使用 T 作爲方法的返回類型

    public <T> T…

  • 使用 T 作爲方法的參數類型

    public <T> void doSomething(T t) …

  • 使用 T 作爲方法的泛型參數的類型參數

    public <T> void doSomething(List<T> listT)…

五、泛型類、方法的使用

5.1 泛型實現類

指類型參數指定爲一個確定的單一類,如 String 對應 AClass<String>,它表示:

一個泛型實現類,類型參數是 String(即 AClass<T>,使用時 T 已經被指定爲 String)

5.2 通配類

5.2.1 AClass<?>

它代表一批泛型實現類,類型參數可以是任何類。

5.2.2 AClass<? extends BClass>

它代表一批泛型實現類,這批實現類的特點是:

  • 它們的類型參數只能是 BClass 的子類。
  • 它們自己,都是 AClass<? extends BClass> 的子類。

這種泛型實現類通配類的父子關係,和泛型實現類的類型參數通配類的類型參數的父子關係相同的關係,稱爲協變

當實現類轉爲 AClass<? extends BClass> 時:

  • 可以 get 到 BClass,因爲所有實現類的類型參數的共同上界就是 BClass。
  • 不能 set 任何值,因爲不確定實現類的類型參數是哪個 BClass 的子類。

5.2.3 AClass<? super BClass>

它代表一批泛型實現類,這批實現類的特點是:

  • 它們的類型參數只能是 BClass 的父類。
  • 它們自己,都是 AClass<? super BClass> 的子類。

這種泛型實現類通配類的父子關係,和泛型實現類的類型參數通配類的類型參數的父子關係相反的關係,稱爲逆變

當實現類轉爲 AClass<? super BClass> 時:

  • 不能 get 到 BClass,只能 get 到 Object,因爲所有實現類的類型參數的共同上界只有 Object。
  • 可以 set BClass 及其子類,因爲一定是覆蓋真正的實現類的類型參數的。

六、代碼示例

public class ChangeJava {
    class A {
    }

    class B extends A {
    }

    class C extends B {
    }

    class AClass<T> {
        private T mT;

        void set(T u) {
            mT = u;
        }

        T get() {
            return mT;
        }
    }

    private void doSomething() {
        AClass<String> aClass = new AClass<>();
        AClass<Object> aClass1 = new AClass<>();
        aClass1 = aClass; // 報錯

        AClass<A> aClassA = new AClass<>();
        AClass<B> aClassB = new AClass<>();
        AClass<C> aClassC = new AClass<>();

        AClass<? extends B> aClassExtendB1 = aClassA; // 報錯
        AClass<? extends B> aClassExtendB2 = aClassB;
        AClass<? extends B> aClassExtendB3 = aClassC;
        B b2 = aClassExtendB2.get(); // 可以 get 到 B
        aClassExtendB2.set(); // 報錯,set 任何值都會報錯

        AClass<? super B> aClassSuperB1 = aClassA;
        AClass<? super B> aClassSuperB2 = aClassB;
        AClass<? super B> aClassSuperB3 = aClassC; // 報錯
        Object o = aClassSuperB1.get(); // 只能 get 到 Object
        aClassSuperB1.set(new A()); // 報錯,set 除 B 及其子類以外的類型就會報錯
        aClassSuperB2.set(new B());
        aClassSuperB2.set(new C());
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章