java泛型

 泛型的構成

由泛型的構成引出了一個類型變量的概念。根據Java語言規範,類型變量是一種沒有限制的標誌符,產生於以下幾種情況:

  • 泛型類聲明
  • 泛型接口聲明
  • 泛型方法聲明
  • 泛型構造器(constructor)聲明

泛型類和接口

如果一個類或接口上有一個或多個類型變量,那它就是泛型。類型變量由尖括號界定,放在類或接口名的後面:

1 public interface List<T> extends Collection<T> {
2 ...
3 }

簡單的說,類型變量扮演的角色就如同一個參數,它提供給編譯器用來類型檢查的信息。

 

泛型方法和構造器(Constructor)

非常的相似,如果方法和構造器上聲明瞭一個或多個類型變量,它們也可以泛型化。

1 public static <t> T getFirst(List<T> list)

這個方法將會接受一個List<T>類型的參數,返回一個T類型的對象。

 

通配符

在本文的前面的部分裏已經說過了泛型類型的子類型的不相關性。但有些時候,我們希望能夠像使用普通類型那樣使用泛型類型:

  • 向上造型一個泛型對象的引用
  • 向下造型一個泛型對象的引用

向上造型一個泛型對象的引用

例如,假設我們有很多箱子,每個箱子裏都裝有不同的水果,我們需要找到一種方法能夠通用的處理任何一箱水果。更通俗的說法,A是B的子類型,我們需要找到一種方法能夠將C<A>類型的實例賦給一個C<B>類型的聲明。

爲了完成這種操作,我們需要使用帶有通配符的擴展聲明,就像下面的例子裏那樣:

1 List<Apple> apples = new ArrayList<Apple>();
2 List<? extends Fruit> fruits = apples;

“? extends”是泛型類型的子類型相關性成爲現實:Apple是Fruit的子類型,List<Apple> 是 List<? extends Fruit> 的子類型。

 

? super

使用 ? super 通配符一般是什麼情況?讓我們先看看這個:

1 List<Fruit> fruits = new ArrayList<Fruit>();
2 List<? super Apple> = fruits;

我們看到fruits指向的是一個裝有Apple的某種超類(supertype)的List。同樣的,我們不知道究竟是什麼超類,但我們知道Apple和任何Apple的子類都跟它的類型兼容。既然這個未知的類型即是Apple,也是GreenApple的超類,我們就可以寫入:

1 fruits.add(new Apple());
2 fruits.add(new GreenApple());

如果我們想往裏面加入Apple的超類,編譯器就會警告你:

1 fruits.add(new Fruit());
2 fruits.add(new Object());

因爲我們不知道它是怎樣的超類,所有這樣的實例就不允許加入。

從這種形式的類型裏獲取數據又是怎麼樣的呢?結果表明,你只能取出Object實例:因爲我們不知道超類究竟是什麼,編譯器唯一能保證的只是它是個Object,因爲Object是任何Java類型的超類。

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章