Java泛型總結(jié)

1、為什么使用泛型

泛型是指參數(shù)化類型的能力。可以定義帶有泛型類型的類或類,隨后編譯器會使用具體的類型來代替它。
使用泛型會有如下好處:
1、類型安全。泛型的主要目的是為了提高Java程序的類型安全。
2、消除強制類型轉(zhuǎn)換。消除代碼中的強制類型轉(zhuǎn)換,提高代碼的可讀性,減少出錯的機會。
3、潛在的性能收益。為JVM優(yōu)化提供可能性

2、泛型的原理

Java有Java編譯器和Java虛擬機,編譯器將Java源代碼轉(zhuǎn)換為.class文件,虛擬機加載并運行.class文件。對于泛型類,Java編譯器會將泛型代碼轉(zhuǎn)換為普通的非泛型代碼,將類型參數(shù)T擦除,替換為Object,插入必有的強制類型轉(zhuǎn)換。這樣做是為了實現(xiàn)兼容性的。知道這一點對于理解Java泛型的許多限制很有用。

3、泛型的使用

泛型類的定義

class 類名稱 <泛型標識:可以隨便寫任意標識號,標識指定的泛型的類型{
  private 泛型標識 /*(成員變量類型)*/ var; 
  }
}

泛型接口的定義

//定義一個泛型接口
public interface Generator<T> {
    public T next();
}

泛型方法的定義

public <T> T genericMethod(Class<T> tClass)throws InstantiationException ,
  IllegalAccessException{
        T instance = tClass.newInstance();
        return instance;
}

總結(jié):泛型類和泛型接口的類型參數(shù)都是跟在接口名或類名之后,而泛型方法的類型參數(shù)在方法返回值之前。

4、泛型的局限

1、不能使用基本類型實例化類型參數(shù)
因為泛型在執(zhí)行類型擦除后,變成了Object類型的域,而Object是不能存儲如int這樣的基本類型
2、不能創(chuàng)建參數(shù)類型的數(shù)組
3、不能實例化類型變量T
因為在編譯的過程中就進行了類型擦除,在需要的實例化的時候找到合適的構(gòu)造函數(shù)
4、泛型類的靜態(tài)上下文中類型參數(shù)失效
參數(shù)類型是在實例化泛型類型的時候才會傳入,而靜態(tài)的上下文會脫離具體類而存在,所以類型參數(shù)會失效。

5、泛型中T ? extends super的理解

在這個問題上,可以分為兩類來說明,首先是 T 和?表示類型,而extends和super表示上限。
在泛型定義的時候,使用T,T extends,或者T super等,如果需要多個不同類型的泛型,則可以加上E S等,其實使用 T E S沒有太大的區(qū)別僅僅是字母的名字不相同而已。

        //在泛型的使用中,對于賦值的語句
        //應該從兩個方面來理解,等號左邊
        //定義了變量的類型,如list是一個能夠存放Number子類的list。
        //等號右邊就是要賦值的內(nèi)容,只要符合就可以賦值成功
        List<? extends Number> list = null;
        List<Integer> list1 = new ArrayList<>();
        //對于使用通配符定義的泛型類型變量,
        //只能訪問其中的值,不能通過該變量
        //來修改集合中的內(nèi)容,但可以通過原
        //來的集合來修改集合的內(nèi)容。
        list1.add(9);
        list = list1;
        System.out.println(list.get(0));
        list1.add(10);
        System.out.println(list.get(1));

在定義類或者方法時候

class TestAnimals <T extends Annimals>{
    T anni;
    public TestAnimals(T anni) {
        this.anni = anni;
    }
    public void test() {
        anni.say();
    }
}
//這種方法是有問題的,因為在進行類型擦除的時候無法知道上限
class TestAnimals <T super Dog>{
    T anni;
    public TestAnimals(T anni) {
        this.anni = anni;
    }
    public void test() {
        anni.say();
    }
}

但是使用泛型的時候,可以使用?來定義接受參數(shù)的上限和下限。
盡管使用通配符?,但是在具體的一次使用中還是只能有一個確定的類型。

        List<?> listOrg1 = null;
        List<Integer> list1 = new ArrayList<>();
        List<Object> list2 = new ArrayList<>();        
        listOrg1 = list1; 
        listOrg1 = list2;
        //可以對已經(jīng)賦過值得泛型變量重新賦值,在
        //具體一次使用泛型變量的過程中還是只有一個
        //具體的類型。
        List<? super Number> listOrg1 = null;
        List<Integer> list1 = new ArrayList<>();
        List<Object> list2 = new ArrayList<>();        
        listOrg1 = list1; //編譯錯誤
        listOrg1 = list2;
        
        List<? extends Number> listOrg2 = null;
        List<Integer> list3 = new ArrayList<>();
        List<Object> list4 = new ArrayList<>();
        listOrg2 = list3;
        listOrg2 = list4;//編譯錯誤
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內(nèi)容