解析java泛型(一)

?????對(duì)于我們java中的泛型,可能很多人知道怎么使用并且使用的還不錯(cuò),但是我認(rèn)為想要恰到好處的使用泛型偷俭,還是需要深入的了解一下它的各種概念和內(nèi)部原理。本文將盡可能的囊括java泛型中的重要的概念缰盏。主要內(nèi)容如下:

  • 泛型的定義及為什么要使用泛型
  • 定義一個(gè)簡(jiǎn)單的泛型類
  • 定義一個(gè)簡(jiǎn)單的泛型方法
  • 類型參數(shù)的限定
  • 泛型內(nèi)部實(shí)現(xiàn)的基本原理
  • 泛型通配符(難點(diǎn))
  • 泛型的其他實(shí)現(xiàn)細(xì)節(jié)

一涌萤、何謂泛型
?????泛型程序設(shè)計(jì)意味著編寫的代碼可以被不同中類型的對(duì)象重用。例如:MyList<T>,MyList<Integer>是一種類型口猜,MyList<String>也是一種類型负溪,但是使用的代碼塊都是MyList<T>,這也就是java中引入泛型的一種原因:可以增強(qiáng)代碼的復(fù)用性济炎,當(dāng)然這種限定死類型的方式也會(huì)使得代碼的安全性和可讀性更高川抡。

二、一個(gè)簡(jiǎn)單的泛型類
先看一個(gè)完整的泛型類:

/*一個(gè)簡(jiǎn)單的泛型類的聲明如下*/
public class Pair<T> {
    private T a;
    private T b;
    public Pair(T a, T b){
        this.a = a;
        this.b = b;
    }
}

?????由此可以看出來(lái)须尚,泛型類型和普通類型的區(qū)別主要在于:類名之后多了個(gè)<T>崖堤,并且實(shí)例域類型可以不是具體的類型而是不確定的T類型。其中耐床,我們管T叫做類型變量密幔,類型變量一般使用大寫字母表示并且很短(在java中使用E表示集合的元素類型,K和V分別表示關(guān)鍵字和值的類型)撩轰。
使用具體的類型來(lái)替換類型變量的過程我們叫做實(shí)例化泛型類型胯甩。例如:Pair<Integer>,<Double>等昧廷。這其中需要注意的是:java中的9中基本類型是不能作為類型變量的,也就是:Pair<int>,是會(huì)不允許的偎箫。當(dāng)然木柬,聲明一個(gè)泛型類時(shí),不局限于一個(gè)類型變量镜廉,可以由多個(gè)類型變量弄诲,例如:

/*聲明兩個(gè)類型變量也是可以的*/
public class Pair<T,U> {
    private T a;
    private U b;
    public Pair(T a, U b){
        this.a = a;
        this.b = b;
    }
}
//Pair<String,Integer> p new Pair<>("abc",12);
//創(chuàng)建泛型類實(shí)例變量的時(shí)候,可以省略類型變量娇唯,編譯器可以推測(cè)出來(lái)

三、一個(gè)簡(jiǎn)單的泛型方法
?????怎么定義泛型類寂玲,我們已經(jīng)介紹過了塔插,接下來(lái)我們一起看看泛型方法是如何定義和調(diào)用的。

/*泛型類中定義了一個(gè)泛型方法*/
public class Pair<T> {
    //聲明一個(gè)泛型方法
    public <T> T getA(T c){
        return c;
    }
}
/*main函數(shù)中調(diào)用泛型方法*/
public class Test2 {
    public static void main(String[] args){
        Pair<Integer> p = new Pair<Integer>(1,2);
        //調(diào)用泛型方法
        System.out.println(p.<Integer>show(10));
    }
}

?????我們可以看到拓哟,聲明一個(gè)泛型方法:public <T > T getA(T c)想许,<T >放在返回值前面,修飾符后面断序,T表示返回類型流纹。泛型方法的調(diào)用:p.<Integer>show(10),在方法名前面放置類型變量,當(dāng)然也可以選擇省略违诗,當(dāng)編譯器沒有足夠的信息推測(cè)出來(lái)時(shí)就會(huì)報(bào)錯(cuò)漱凝,那時(shí)你再添加也不遲(但是,如果你能減輕計(jì)算機(jī)的工作的話诸迟,想必是可以提高效率的)
?????小結(jié)一下茸炒,泛型類和泛型方法。泛型類中可以聲明泛型方法也可以聲明普通方法阵苇,泛型方法可以出現(xiàn)在泛型類中也可以出現(xiàn)在普通類中壁公,也就是它們之間并沒有什么約束關(guān)系器瘪。
四拥褂、類型變量的限定
前面我們已經(jīng)知道了什么是類型變量,我們看一段代碼:

public class Pair<T> {
    public static <T> int myCompare(T a,T b){
        return a.compareTo(b);//此處編譯不通過
    }
}

?????我們知道男翰,如果想要使用compareTo方法快耿,就要實(shí)現(xiàn)Comparable接口囊陡,或者繼承實(shí)現(xiàn)了此接口的類。此處想要使得程序正確润努,有兩種辦法关斜。第一種:使類繼承Comparable接口并且實(shí)現(xiàn)compareTo方法。第二種:就是使用類型變量限定铺浇。如下:

/*限定變量類型*/
public class Pair<T> {
    public static <T extends Comparable> int myCompare(T a,T b){
        return a.compareTo(b);
    }
}

?????細(xì)心的同學(xué)可能已經(jīng)發(fā)現(xiàn)痢畜,相比于原來(lái)的方法,就是使類型變量繼承與Comparable接口。原來(lái)的<T >變成了<T extends Comparable>丁稀,表示:原來(lái)的T可以是任意類型的吼拥,而現(xiàn)在的T被限制必須實(shí)現(xiàn)了Comparable 接口,就是說(shuō)线衫,凡是使用此泛型的類都是直接或者間接繼承了Comparable 接口并實(shí)現(xiàn)其中方法的凿可。所以,一旦我們將T限定了授账,就不用考慮實(shí)現(xiàn)Comparable 接口的事情了枯跑,程序的封裝性更強(qiáng)了。
?????對(duì)類型變量的限定可以由多個(gè)限定白热,它們之間使用&分隔敛助,而使用逗號(hào)分隔類型變量∥萑罚看個(gè)例子:

<T extends Comparable>    //一個(gè)類型變量的一個(gè)類型限定

<T extends Comparable & Serializable> //一個(gè)類型變量的兩個(gè)類型限定

<T extends Comparable纳击,U extends Serializable>//兩個(gè)類型變量的類型限定

五、泛型實(shí)現(xiàn)的基本原理
?????討論了這么多的泛型方法攻臀,泛型類以及各種使用技巧焕数,接下來(lái),我們一起看看虛擬機(jī)實(shí)際執(zhí)行時(shí)是怎么對(duì)待我們的泛型的刨啸。我們都知道java中有編譯器和虛擬機(jī)堡赔,但實(shí)際上我們的泛型在這兩者看來(lái)是不一樣的,也就是說(shuō)呜投,虛擬機(jī)是不認(rèn)識(shí)泛型的加匈,而只有我們強(qiáng)大的編譯器是認(rèn)識(shí)泛型的。那他們是怎么實(shí)現(xiàn)統(tǒng)一的呢仑荐?接下來(lái)我們?cè)敿?xì)來(lái)看雕拼。
?????在java中,無(wú)論何時(shí)定義了一個(gè)泛型粘招,它都會(huì)自動(dòng)生成一個(gè)相應(yīng)的原始類型啥寇。我們叫這個(gè)過程為:類型擦除。例如下面的代碼:

/*這是一段泛型類的代碼*/
public class Pair<T> {
    private T a;
    private T b;

    public T getA(){
        return this.a;
    }
    
    public T getB(){
        return this.b;
    }
}
經(jīng)過類型擦除之后生成原始類型:
public class Pair{
    private Object a;
    private Object b;

    public Object getA(){
        return this.a;
    }
    
    public Object getB(){
        return this.b;
    }
}

?????經(jīng)過對(duì)比洒扎,我們可以得出結(jié)論:去除了泛型的標(biāo)志性符號(hào)<>并且所有的T類型都被替換成Object類型了辑甜。難道我們的類型擦除就是將所有的未知類型轉(zhuǎn)換為Object類型嗎?當(dāng)然不是袍冷,類型擦除是有規(guī)則的而不是一味的將未知類型T轉(zhuǎn)換成Object類型的磷醋。
?????對(duì)于有限定的類型變量就將用類型變量的第一個(gè)限定類型替換。如:Pair<T extends Comparable & Serializable>胡诗,就會(huì)選擇用Comparable替換所有的T并去除修飾在類后面的泛型符號(hào)邓线,生成原始類型淌友。
?????對(duì)于沒有限定類型的類型變量就默認(rèn)使用Object替換類型變量。例如:Pair<T>就會(huì)使用Object替換所有的T類型變量骇陈。
?????最后小結(jié)一下震庭,類型擦除針對(duì)是否有類型限定類型,根據(jù)不同的狀況進(jìn)行替換生成相應(yīng)的原始類型供jvm調(diào)用你雌。
未完器联,待續(xù)。婿崭。拨拓。。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末氓栈,一起剝皮案震驚了整個(gè)濱河市千元,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌颤绕,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,539評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件祟身,死亡現(xiàn)場(chǎng)離奇詭異奥务,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)袜硫,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評(píng)論 3 396
  • 文/潘曉璐 我一進(jìn)店門氯葬,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人婉陷,你說(shuō)我怎么就攤上這事帚称。” “怎么了秽澳?”我有些...
    開封第一講書人閱讀 165,871評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵闯睹,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我担神,道長(zhǎng)楼吃,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,963評(píng)論 1 295
  • 正文 為了忘掉前任妄讯,我火速辦了婚禮孩锡,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘亥贸。我一直安慰自己躬窜,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,984評(píng)論 6 393
  • 文/花漫 我一把揭開白布炕置。 她就那樣靜靜地躺著荣挨,像睡著了一般男韧。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上垦沉,一...
    開封第一講書人閱讀 51,763評(píng)論 1 307
  • 那天煌抒,我揣著相機(jī)與錄音,去河邊找鬼厕倍。 笑死寡壮,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的讹弯。 我是一名探鬼主播况既,決...
    沈念sama閱讀 40,468評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼组民!你這毒婦竟也來(lái)了棒仍?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤臭胜,失蹤者是張志新(化名)和其女友劉穎莫其,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體耸三,經(jīng)...
    沈念sama閱讀 45,850評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡乱陡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,002評(píng)論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了仪壮。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片憨颠。...
    茶點(diǎn)故事閱讀 40,144評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖积锅,靈堂內(nèi)的尸體忽然破棺而出爽彤,到底是詐尸還是另有隱情,我是刑警寧澤缚陷,帶...
    沈念sama閱讀 35,823評(píng)論 5 346
  • 正文 年R本政府宣布适篙,位于F島的核電站,受9級(jí)特大地震影響蹬跃,放射性物質(zhì)發(fā)生泄漏匙瘪。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,483評(píng)論 3 331
  • 文/蒙蒙 一蝶缀、第九天 我趴在偏房一處隱蔽的房頂上張望丹喻。 院中可真熱鬧,春花似錦翁都、人聲如沸碍论。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,026評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)鳍悠。三九已至税娜,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間藏研,已是汗流浹背敬矩。 一陣腳步聲響...
    開封第一講書人閱讀 33,150評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蠢挡,地道東北人弧岳。 一個(gè)月前我還...
    沈念sama閱讀 48,415評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像业踏,于是被迫代替她去往敵國(guó)和親禽炬。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,092評(píng)論 2 355

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

  • 一勤家、為什么要使用泛型 1.類型參數(shù)的好處 類型安全:泛型的主要目標(biāo)是提高 Java 程序的類型安全腹尖。通過知道使用泛...
    SeanMa閱讀 7,084評(píng)論 1 18
  • 引言:泛型一直是困擾自己的一個(gè)難題,但是泛型有時(shí)一個(gè)面試時(shí)老生常談的問題伐脖;今天作者就通過查閱相關(guān)資料簡(jiǎn)單談?wù)勛约簩?duì)...
    cp_insist閱讀 1,847評(píng)論 0 4
  • 前言 JDK1.5號(hào)稱是Java最重要的版本更新热幔,而泛型又是JDK1.5中一個(gè)最重要的特征。使用泛型機(jī)制編寫的程序...
    WinsonWu閱讀 639評(píng)論 0 0
  • 泛型的好處 使用泛型的好處我覺得有兩點(diǎn):1:類型安全 2:減少類型強(qiáng)轉(zhuǎn) 下面通過一個(gè)例子說(shuō)明: 假設(shè)有一個(gè)Tes...
    德彪閱讀 1,126評(píng)論 0 0
  • 《活法》中一小節(jié)”利他” 利他之心讼庇,在佛教就是與人為善的慈悲心断凶。在基督教就是愛。現(xiàn)在說(shuō)的樸實(shí)...
    徐書軍閱讀 159評(píng)論 0 0