Java-泛型

今天記錄一下Java中的泛型,畢竟大家在項目中經(jīng)常用到或者看到過。
參考:http://www.itdecent.cn/p/95f349258afb

1.什么是泛型

泛型是Java SE 1.5的新特性,泛型的本質(zhì)是參數(shù)化類型,也就是說所操作的數(shù)據(jù)類型被指定為一個參數(shù),Java語言引入泛型的好處是安全簡單

2.泛型的特性

在Java SE 1.5之前,沒有泛型的下,通過對類型Object的引用來實現(xiàn)參數(shù)的“任意化”,“任意化”帶來的缺點是要做顯式的強制類型轉(zhuǎn)換而這種轉(zhuǎn)換是要求開發(fā)者對實際參數(shù)類型預知的情況下進行的。對于強制類型轉(zhuǎn)換錯誤的情況,編譯器在編譯期間可能不提示錯誤,在運行的時候才出現(xiàn)異常,這是一個安全隱患。泛型的好處是在編譯的時候檢查類型安全,并且所有的強制轉(zhuǎn)換都是自動和隱式的,可以提高代碼的重用率。
拿我們常用的List集合舉個例子:

List mList =new LinkedList();
mList.add("aaa");
int a = (int) mList.get(0);

不用說這樣一運行肯定會報一個類型不能轉(zhuǎn)換的錯誤。注意雖然不正確但編譯器沒有發(fā)現(xiàn),運行時才會報錯,那我們試試加泛型的。

image.png

其實我們常用的集合就是加了泛型的,只不過大家可能不在意。
總結(jié):
Object的參數(shù)"任意化"在編譯期間不能發(fā)現(xiàn)錯誤,運行時可能報錯,是個安全隱患,而泛型可以在編譯期間就可以檢查類型安全。

3.常見的泛型分類

泛型有三種分類:泛型類、泛型接口、泛型方法

3.1泛型類

泛型類的定義方式:

public  class generic<泛型通配符>{
private 泛型通配符    genericClass;
 //泛型構(gòu)造方法形參 parameter的類型也為T,T的類型由外部指定
public Generic(T parameter) {
        this.genericClass =  parameter;
    }
}

這個泛型通配符可以隨意取值:比如A,B,C,D.(注意得是大寫)但我們通常都取?、K、V各自有不同的含義:

  • ?:表示不確定的java類型
  • T:(type) 表示具體的一個java類型
  • K V (key value) 分別代表java鍵值中的Key Value
  • E: (element) 代表Element

我們就以K,V這種的通配符定義一個泛型類,代碼如下:

public interface GenericInter<K,V> {
    public K getKey();
    public V getValue();
}


public class GenericClass<K,V> extends GenericInter{

    public K key;
    public V value;

    public GenericClass(K key, V value) {
        this.key = key;
        this.value = value;
    }
    

    @Override
    public Object getKey() {
        return key;
    }

    @Override
    public Object getValue() {
        return value;
    }
}

調(diào)用:

    GenericClass genericClass =new GenericClass("0","張三");
    GenericClass mGenericClass =new GenericClass(1,111);

如果要定義超過兩個,三個或三個以上的泛型參數(shù)可以使用T1, T2, ..., Tn,列如:

public class GenericClass<T1,T2,T3>{

        public T1 t1;
        public T2 t2;
        public T3 t3;

        public GenericClass(T1 t1, T2 t2, T3 t3) {
            this.t1 = t1;
            this.t2 = t2;
            this.t3 = t3;
        }
    }
3.2泛型接口

我們上面定義泛型類的時候用的就是泛型接口,泛型接口與泛型類的定義及使用基本相同。泛型接口常被用在各種類的生產(chǎn)器中:

public interface GenericInter<K,V> {
    public K getKey();
    public V getValue();
}
3.3泛型方法

先說一下泛型類和泛型方法的區(qū)別:泛型類,是在實例化類的時候指明泛型的具體類型;泛型方法,是在調(diào)用方法的時候指明泛型的具體類型 。泛型方法相對比較復雜,我們來看一下:

3.3.1

image.png

大家覺得getT()是泛型方法不?答案是:No,
getT()方法雖然使用了泛型,但它的泛型是在泛型類中已經(jīng)聲明了的泛型,所以它才可以使用這個T泛型,getT()不是泛型方法,它算是一個普通成員方法。
image.png

大家覺得showGeneric(genericClass<?> obj)是泛型方法不?答案是:No,
showGeneric(genericClass<?> obj)也是一個普通的方法,只不過使用了泛型通配符?,這也印證了泛型通配符?是一種類型實參
image.png

真正的泛型方法長這樣:

  class genericClass<T> {
        public T t;

        public genericClass(T t) {
            this.t = t;
        }

        public T getT(){
            return t;
        }

        //正確的泛型方法
        public <T> T getGenericClassT(genericClass<T> obj){
            return obj.getT();
        }
    }

要點:真正的泛型方法,在public與返回值之間的<T>必不可少,這表明這是一個泛型方法,并且聲明了一個泛型T。但T可以出現(xiàn)在這個泛型方法的任意位置, 泛型的數(shù)量也可以為任意多個

3.3.2 泛型方法和可變參數(shù)
image.png

這個沒啥好說的。

3.3.3 泛型數(shù)組

關(guān)于如何正確創(chuàng)建泛型數(shù)組:

  //錯誤創(chuàng)建泛型數(shù)組的方式
        List<String> [] mList  =new ArrayList<String>[10];
        //正確創(chuàng)建泛型數(shù)組方式一,通過通配符?
        List<?> [] mListTwo  =new ArrayList<?>[10];
        //正確創(chuàng)建泛型數(shù)組方式二
        List<String>[] mListThree = new ArrayList[10];

總結(jié):在java中是不能創(chuàng)建一個確切的泛型類型的數(shù)組

4.各種泛型的區(qū)別

4.1 List<T>,List<Object>,List<?>的區(qū)別?

ArrayList<T> al=new ArrayList<T>(); 指定集合元素只能是T類型

ArrayList<?> al=new ArrayList<?>(); 集合元素可以是任意類型,沒有意義,一般只是為了說明用法.

  • Object和T不同點在于,Object是一個實打?qū)嵉念?并沒有泛指誰,而T可以泛指Object,比方public void printList(List<T> list){}方法中可以傳入List<Object> list類型參數(shù),也可以傳入List<String> list類型參數(shù),但是public void printList(List<Object> list){}就只可以傳入List<Object> list類型參數(shù),因為Object類型并沒有泛指誰,是一個確定的類型
  • ?和T區(qū)別是?是一個不確定類,?和T都表示不確定的類型 ,但如果是T的話,函數(shù)里面可以對T進行操作,比方 T car = getCar(),而不能用? car = getCar()。
4.2 T,Class,Class<T>,Class<?>區(qū)別?
  • T,是一種具體的類,例如String,List,Map......等等,這些都是屬于具體的類。
  • Class,是一個類,但Class是存放上面String,List,Map.....。
    注:獲取Class的三種方式:
    1.調(diào)用Object類的getClass()方法來得到Class對象
    image.png
  1. 使用Class類的中靜態(tài)forName()方法獲得與字符串對應的Class對象
    image.png

3.如果T是Java類型則直接T.calss

image.png

  • Classy<T> 在實例化的時候,T要替換成具體類,使用Class<T>還有一個好處就是不用強轉(zhuǎn).
    我們看一下不加泛型,反射創(chuàng)建一個類對象,需要強轉(zhuǎn):
    image.png

    使用Class<T>泛型后,不用強轉(zhuǎn)了:
    image.png
  • Class<?>它是個通配泛型,?可以代表任何類型,主要用于聲明時的限制情況
    例如,你可以聲明:
    public Class<?> clazz;
    但不能聲明:
    public Class<T> clazz;

因為T需要指定類型,所以當不知道定聲明什么類型的Class的時候可以定義一個Class<?>,Class<?>可以用于參數(shù)類型定義,方法返回值定義等。

以上就是今天的全部內(nèi)容!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

  • 轉(zhuǎn)載自這里,這哥們也是轉(zhuǎn)載但是沒注明....所以找不到原作者 1. 概述 泛型在java中有很重要的地位,在面向?qū)?..
    琴匣自鳴閱讀 1,360評論 0 14
  • 泛型,一個孤獨的守門者。 大家可能會有疑問,我為什么叫做泛型是一個守門者。這其實是我個人的看法而已,我的意思是說泛...
    程序員BUG閱讀 397評論 0 0
  • 泛型,一個孤獨的守門者。 大家可能會有疑問,我為什么叫做泛型是一個守門者。這其實是我個人的看法而已,我的意思是說泛...
    傳奇內(nèi)服號閱讀 441評論 0 0
  • 開發(fā)人員在使用泛型的時候,很容易根據(jù)自己的直覺而犯一些錯誤。比如一個方法如果接收List作為形式參數(shù),那么如果嘗試...
    時待吾閱讀 1,125評論 0 3
  • 如果你問我,人類史上永恒不衰的經(jīng)典主題是什么,我會說“愛,戰(zhàn)爭和死亡”。《演員的誕生》上第一次接觸《最愛》,《甄嬛...
    浮木杜郎閱讀 460評論 0 1

友情鏈接更多精彩內(nèi)容