天天看點

Java中的泛型(Generic)

JDK5以前,對象儲存到集合中就會失去其特性,取出時通常要程式員手工進行類型的強制轉換,這樣不可避免就會引發程式的一些安全性問題.例如:

ArrayList list = new ArrayList();
list.add("abc");
Integer num = (Integer)list.get();//運作時出錯,但編碼時發現不了

list.add(new Random());
list.add(new ArrayList());
for(int i=;i<list.size();i++){
    (?)list.get(i);//這裡取出的對象應該轉換成什麼類型
}
           

1.集合泛型:在沒有泛型之前,集合中存入的資料,類型就會丢掉,在取出資料時,需要做強制類型轉換,就有轉換的風險.而這種風險,在編譯階段是沒有辦法檢查出來的.引入泛型之後,在定義集合的過程中可以指定集合中存儲的類型,當存入非這種類型的資料時,編譯時會報錯,取出資料時也不需要強轉:

List list = new ArrayList();

泛型的基本術語,以ArrayList為例: <>念着為typeof

·ArrayList中的E稱為類型參數變量

·ArrayList中的Integer稱為實際參數類型

·整個稱為ArrayList泛型類型

·整個ArrayList稱為參數化的類型ParameterizedType

如果兩邊都有泛型,則要求泛型必須一緻,也可以隻有一邊有而另一邊沒有

ArrayList list = new ArrayList();

ArrayList list = new ArrayList();

ArrayList list = new ArrayList ();//–考慮相容1.5之前的老程式

ArrayList list = new ArrayList();

2.自定義泛型

方法類型:定義在方法上的泛型叫做方法泛型,作用的範圍的目前方法内部

泛型在使用之前必須先定義,其中的字母可以是任意字母,但是通常都是大寫字母

可以認為,當方法在被調用到時,虛拟機自動判斷出泛型的具體類型.

public static <T> void doxx(T t){}
        public <T> T getSome(){}
           
類上的泛型:定義在類上的泛型叫做類泛型,作用範圍是整個類中都可以使用
           
public class GenericDao<T>{}
           
可以認為,在使用這個類時,就需要指定出泛型的具體類型.如果不确定,則泛型是它的上邊界類型的.
    靜态方法不能使用類上定義的泛型,如果想使用泛型靜态方法必須自己定義泛型.
           

*泛型通配符

因為泛型沒有繼承關系,是以當需要用一個泛型引用不同的泛型實作時,泛型中他們的的共同的父類是不可以的.這時候,就引入了一個新的概念,叫做泛型通配符?.注意泛型通配符隻能用在泛型引用中,用來引用不同的泛型實作,不能出現在實作中.

List<?> list = null;
list = new ArrayList<String>();
list = new ArrayList<Integer>();
           

*泛型的邊界:

如果沒有指定泛型預設可以接受任意類型,有時希望進一步限制,此時可以使用泛型的邊界:

extends - 用來指定泛型的上邊界,使用在泛型的通配符和泛型定義中,指定具體的泛型實作必須是指定的類或其子類.

壞處是:在傳入對象時,隻能傳入null.

好處是:在擷取到泛型的對象時,可以調用上邊界的方法.

super - 用來指定泛型的下邊界,使用在泛型的通配符中,指定具體的泛型實作必須是指定類或者超類.下邊界不能使用在類泛型上

好處是:傳入對象時,可以傳入下邊界的子孫類對象

壞處是:擷取到泛型對象時,隻能調用Object身上的方法.

例:

List<? extends Object> list = null;
list = new ArrayList<String>();//這是可以的,因為String是上邊界的子類
list.add(null);//隻能增加null,因為上邊界給定的是Object,那麼具體不管加入什麼類型,在最後轉換的時候都可能出錯.隻有null是任何類的子類
           
List<? super Integer> list = null;
list = new ArrayList<Number>();//可以的,因為下邊界是String
list.add(new Number());//可以的,因為已經确定了下邊界.但是這時不能使用String身上的具體方法,隻能使用Object身上的方法.因為泛型下邊界定義為String,不知道具體會實作稱為什麼樣的類型