Java那些事-泛型通配符

Java的類型通配符,能夠出如今類、方法上面。最經常使用的方式就是集合類,例如List,Set等類上面。java

通配符類型

  • 有泛型參數 List
  • 有無類型標識 List< ? >
  • 有通用的標識 List< object >
  • 邊界通配符 List<? extends Class>
  • 邊界通配符 List<? super Class>

本文主要討論的是最後的關於邊界的通配符類型。數組

看一個例子

public static void main(String[] args) {
        List<B> bList = new ArrayList();
        bList.add(new A());
        bList.add(new B());
        bList.add(new C());
        A a3 = bList.get(0);
        B b3 = bList.get(0);
        C C3 = bList.get(0);

        List<? extends B> bExtends = new ArrayList();
        bExtends.add(new A());
        bExtends.add(new B());
        bExtends.add(new C());
        A a1 = bExtends.get(0);
        B b1 = bExtends.get(0);
        C C1 = bExtends.get(0);

        List<? super B> bSuper = new ArrayList();
        bSuper.add(new A());
        bSuper.add(new B());
        bSuper.add(new C());
        A a2 = bSuper.get(0);
        B b2 = bSuper.get(0);
        C C2 = bSuper.get(0);
    }
}
class A {
    String a = "a";
}
class B extends A {
    String b = "b";
}
class C extends B {
    String c = "c";
}

有三個類,繼承關係是A < B < C。
而後聲明瞭三個數組,list,extends,super.
上面的代碼是編譯不經過的。分別在第三、七、11-1三、1六、1九、22-24行。安全

原理分析

List<? extends B> 獲得的是B及B的子類的一個集合。
List<? super B> 獲得的是B及B的父類的一個集合。
List 獲得的是一個B的集合。code

  1. ? extends B 聲明瞭上界標識符、不定下界,而add(E e)的時候,編譯器沒法肯定e須要分配的聲明類型,雖然有實際類型,這個地方跟多態不一致,因此編譯器不經過;而get(int i)的操做,會獲取到一個確定是B的元素,故是安全的。
  2. ? super B正相反,聲明的是下界標識符、不定上界(Object),當add(E e)的時候,添加的是子類型,子類型向上轉型是安全的;get(int i)的時候,並不能肯定拿到的會是一個怎樣的類型,多是Object,也能是A,故也是違規的。
  3. B 聲明的是上下界爲B。add(E e)按照多態性,能夠添加爲B的類型及其子類型;get(int i)返回的必然是B的類型。

代碼錯誤驗證

按照第1條解釋,第三、11-13行的錯誤符合解釋。
按照第2條解釋,第1九、22-24行的錯誤符合解釋。
第七、16行是因爲向下轉型是不安全的,股編譯錯誤。繼承

小結

extends和super別定義了上下限,結論以下面的表格get

extends super T
add unsafe safe safe
get safe unsafe safe
相關文章
相關標籤/搜索