[TOC]
### 泛型的基本概念
java中泛型的引入主要是為了解決兩個方面的問題:
* 集合類型元素在運行期出現類型裝換異常,增加編譯時類型的檢查,
* 解決的時重復代碼的編寫,能夠復用算法。
* 保證**類型安全**
例子:
~~~
ArrayList al = new ArrayList();
al.add("abc");
al.add("124");
al.add("32L");
~~~
我們可以向al集合中添加任何類型的數據。當我們在取出數據的時候需要時候類型轉換,如:
~~~
String s = (String)al.get(0);
String s1 = (String)al.get(1); //在運行期,會報錯,類型轉換錯誤
Long l = (Long)al.get(2);
~~~
由此可以看到,沒有泛型的時候,減少了編譯時的類型檢查,在取出元素時需要程序員對每個元素的類型都了解,否則很可能在運行時出現類型轉換的異常。
那么下面我們通過泛型集合來看看他給我們帶來的好處。
~~~
ArrayList<String> al1 = new ArrayList<String>();
al1.add("abc");
al1.add(1); //編譯時報錯,
~~~
當我們用String參數類型實例化al1后,我們是不能添加int元素的,否則編譯器會報錯,通常在IDE編輯器,如eclipse中會有錯誤標識,與此同時,在取出元素也不需要類型轉換.
~~~
string value = al1.get(0); //不需要類型轉換
~~~
這便是泛型所帶來的好處。
### 泛型的使用
java中的泛型主要使用在類,方法,與接口中。首先,我們來簡單的看看在類上的使用:
~~~
class Factory<T>{
private T value;
public T getValue()
{
return value;
}
public void setValue(T v)
{
this.value = v;
}
}
~~~
添加測試方法:
~~~
Factory<String> f = new Factory<String>();
f.setValue("factory in use");
System.out.println(f.getValue());
~~~
泛型接口的使用:
~~~
interface MyInterface<T,U>{
void show(T t, U u);
}
class ShowTest implements MyInterface<String,Integer>{
@Override
public void show(String t, Integer u) {
System.out.println(t);
System.out.println(u);
}
}
~~~
泛型類型參數作用于類上的時候主要是對多個字段及方法簽名之間的類型約束。作用于方法的時候主要是對方法的的多個參數做相應的約束,在這里方法的泛型類型參數不再舉例,下面我們主要介紹類型參數的約束。
### 類型參數約束
我們看一個小例子,如下代碼所示:
~~~
public static <T> T get(T t1,T t2) {
if(t1.compareTo(t2)>=0);//編譯錯誤 ,the method compareTo(T) is undefined for the type T.
return t1;
}
~~~
可以看到編譯器報錯的信息,對于類型T沒有定義compareTo方法,在java中類型需要比較的話需要實現Comparable接口,從而重寫該方法。 那么我們做如下修改:
~~~
public static <T extends Comparable> T get(T t1,T t2) { //添加類型限定
if(t1.compareTo(t2)>=0);
return t1;
}
~~~
通過限定T extends Comparable 表明,T是實現了Comparable的接口的類型,因此也實現了compareTo方法,因此不會產生編譯期錯誤。
> 類型的多個限定時我們可以使用&來進行分割,并且限定的關鍵詞只能使用extends。與此同時在*接口與類型都存在的情況下,類只能放在第一個,并且只能有一個*,如下所示:
~~~
<T extends Object&Comparable&Serializable>
~~~