Java泛型(一)

一、泛型的定義

1墨辛、什么是java泛型?
泛型是Java SE 1.5的新特性趴俘,泛型的本質(zhì)是參數(shù)化類(lèi)型睹簇,也就是說(shuō)所操作的數(shù)據(jù)類(lèi)型被指定為一個(gè)參數(shù)。
這種參數(shù)類(lèi)型可以用在類(lèi)寥闪、接口和方法的創(chuàng)建中太惠,分別稱(chēng)為泛型類(lèi)、泛型接口疲憋、泛型方法凿渊。

2、為什么需要泛型?
Java語(yǔ)言引入泛型的好處是安全簡(jiǎn)單埃脏√侣啵可以將運(yùn)行時(shí)錯(cuò)誤提前到編譯時(shí)錯(cuò)誤。
在Java SE 1.5之前彩掐,沒(méi)有泛型的情況的下构舟,通過(guò)對(duì)類(lèi)型Object的引用來(lái)實(shí)現(xiàn)參數(shù)的“任意化”,“任意化”帶來(lái)的缺點(diǎn)是要做顯式的強(qiáng)制類(lèi)型轉(zhuǎn)換堵幽,
而這種轉(zhuǎn)換是要求開(kāi)發(fā)者對(duì)實(shí)際參數(shù)類(lèi)型可以預(yù)知的情況下進(jìn)行的狗超。對(duì)于強(qiáng)制類(lèi)型轉(zhuǎn)換錯(cuò)誤的情況,編譯器可能不提示錯(cuò)誤朴下,在運(yùn)行的時(shí)候才出現(xiàn)
異常努咐,這是一個(gè)安全隱患。泛型的好處是在編譯的時(shí)候檢查類(lèi)型安全殴胧,并且所有的強(qiáng)制轉(zhuǎn)換都是自動(dòng)和隱式的渗稍,提高代碼的重用率。

3溃肪、泛型的好處免胃?
(1)類(lèi)型安全。
通過(guò)知道使用泛型定義的變量的類(lèi)型限制惫撰,編譯器可以更有效地提高Java程序的類(lèi)型安全羔沙。
(2)消除強(qiáng)制類(lèi)型轉(zhuǎn)換。
消除源代碼中的許多強(qiáng)制類(lèi)型轉(zhuǎn)換厨钻。這使得代碼更加可讀扼雏,并且減少了出錯(cuò)機(jī)會(huì)。所有的強(qiáng)制轉(zhuǎn)換都是自動(dòng)和隱式的夯膀。
(3)提高性能诗充。

4、泛型使用的注意事項(xiàng)
(1)泛型類(lèi)型變量不能是基本數(shù)據(jù)類(lèi)型诱建。
就比如蝴蜓,沒(méi)有ArrayList<double>,只有ArrayList<Double>俺猿。因?yàn)楫?dāng)類(lèi)型擦除后茎匠,ArrayList的原始類(lèi)中的類(lèi)型變量(T)替換為Object,
但Object類(lèi)型不能存儲(chǔ)double值押袍。

(2)泛型的類(lèi)型參數(shù)可以有多個(gè)诵冒,用逗號(hào)分隔。
Node<T,E,V,K>

(3)不能對(duì)確切的泛型類(lèi)型使用instanceof操作谊惭。如下面的操作是非法的汽馋,編譯時(shí)會(huì)出錯(cuò)侮东。
if( arrayList instanceof ArrayList<String>){}//編譯錯(cuò)誤

(4)不能創(chuàng)建一個(gè)確切的泛型類(lèi)型的數(shù)組。
例如:

List<String>[] ls = new ArrayList<String>[10];//編譯報(bào)錯(cuò)
        List<String>[] list = new ArrayList[10];//正確
        List<?>[] ls = new ArrayList<?>[10];//正確

(5)泛型在靜態(tài)方法和靜態(tài)類(lèi)中的問(wèn)題
泛型類(lèi)中的靜態(tài)方法和靜態(tài)變量不可以使用泛型類(lèi)所聲明的泛型類(lèi)型參數(shù)

        public /*static*/ class StaticGenerator<T> {
            //泛型的靜態(tài)方法
            public static <T> void show(T t){
                System.out.println("泛型測(cè)試:t is " + t);
            }

            /*public static T one;   //編譯錯(cuò)誤
            public static  T print(T one){ //編譯錯(cuò)誤
                return null;
            }*/
        }

因?yàn)榉盒皖?lèi)中的泛型參數(shù)的實(shí)例化是在定義泛型類(lèi)型對(duì)象(例如ArrayList<Integer>)的時(shí)候指定的豹芯,而靜態(tài)變量和靜態(tài)方法不需要使用對(duì)象來(lái)調(diào)用悄雅。
對(duì)象都沒(méi)有創(chuàng)建,如何確定這個(gè)泛型參數(shù)是何種類(lèi)型告组,所以當(dāng)然是錯(cuò)誤的煤伟。但是要注意區(qū)分下面的一種情況:
泛型方法:在泛型方法中使用的T是自己在方法中定義的T,而不是泛型類(lèi)中的T木缝。

(6)泛型類(lèi)型引用傳遞問(wèn)題
在Java中便锨,像下面形式的引用傳遞是不允許的:

        ArrayList<String> arrayList1=new ArrayList<Object>();//編譯錯(cuò)誤
        ArrayList<Object> arrayList2=new ArrayList<String>();//編譯錯(cuò)誤

二、泛型的實(shí)現(xiàn)原理
1我碟、類(lèi)型擦除

    ArrayList<String> arrayString = new ArrayList<String>();
    ArrayList<Integer> arrayInteger = new ArrayList<Integer>();
    System.out.println(arrayString.getClass() == arrayInteger.getClass());//輸出:true

在編譯期間放案,所有的泛型信息都會(huì)被擦除,List<Integer>和List<String>類(lèi)型矫俺,在編譯后都會(huì)變成List類(lèi)型(原始類(lèi)型)吱殉。
Java中的泛型基本上都是在編譯器這個(gè)層次來(lái)實(shí)現(xiàn)的,這也是Java的泛型被稱(chēng)為“偽泛型”的原因厘托。

2友雳、原始類(lèi)型
原始類(lèi)型就是泛型類(lèi)型擦除了泛型信息后,在字節(jié)碼中真正的類(lèi)型铅匹。無(wú)論何時(shí)定義一個(gè)泛型類(lèi)型押赊,相應(yīng)的原始類(lèi)型都會(huì)被自動(dòng)提供。
原始類(lèi)型的名字就是刪去類(lèi)型參數(shù)后的泛型類(lèi)型的類(lèi)名包斑。擦除類(lèi)型變量流礁,并替換為限定類(lèi)型(T為無(wú)限定的類(lèi)型變量,用Object替換)罗丰。

    //泛型類(lèi)型
    class Pair<T> {
        private T value;
        public T getValue() {
            return value;
        }
        public void setValue(T  value) {
            this.value = value;
        }
    }
    //原始類(lèi)型
    class Pair {
        private Object value;
        public Object getValue() {
            return value;
        }
        public void setValue(Object  value) {
            this.value = value;
        }
    }

在Pair<T>中神帅,T是一個(gè)無(wú)限定的類(lèi)型變量,所以用Object替換萌抵。如果是Pair<T extends Number>找御,擦除后,類(lèi)型變量用Number類(lèi)型替換绍填。

3萎坷、橋接方法
Node<T>:聲明Node<String>還是Node<Integer>,到了運(yùn)行期間沐兰,JVM統(tǒng)統(tǒng)視為Node<Object>。
原因:對(duì)于泛型代碼蔽挠,Java編譯器實(shí)際上還會(huì)偷偷幫我們實(shí)現(xiàn)一個(gè)Bridge method(橋接方法)住闯。
解決辦法:

Node<T extends Comparable<T>> 代替 Node<T>
    public class Node<T> {
        public T data;
        public Node(T data) { this.data = data; }
        public void setData(T data) {
            System.out.println("Node.setData");
            this.data = data;
        }
    }
    public class MyNode extends Node<Integer> {
        public MyNode(Integer data) { super(data); }
        public void setData(Integer data) {
            System.out.println("MyNode.setData");
            super.setData(data);
        }
    }

測(cè)試代碼如下:

    MyNode mn = new MyNode(5);
    Node n = mn; // A raw type - compiler throws an unchecked warning
    n.setData("Hello"); // Causes a ClassCastException to be thrown.
    Integer x = mn.data;
    System.out.println(n.toString());
    System.out.println(x);

編譯之后的代碼如下:

    class MyNode extends Node {
        // Bridge method generated by the compiler
        public void setData(Object data) {
            setData((Integer) data);
        }
        public void setData(Integer data) {
            System.out.println("MyNode.setData");
            super.setData(data);
        }
        // ...
    }

歡迎加入學(xué)習(xí)交流群569772982瓜浸,大家一起學(xué)習(xí)交流。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末比原,一起剝皮案震驚了整個(gè)濱河市插佛,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌量窘,老刑警劉巖雇寇,帶你破解...
    沈念sama閱讀 223,126評(píng)論 6 520
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異蚌铜,居然都是意外死亡锨侯,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,421評(píng)論 3 400
  • 文/潘曉璐 我一進(jìn)店門(mén)冬殃,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)囚痴,“玉大人,你說(shuō)我怎么就攤上這事审葬∩罟觯” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 169,941評(píng)論 0 366
  • 文/不壞的土叔 我叫張陵涣觉,是天一觀的道長(zhǎng)痴荐。 經(jīng)常有香客問(wèn)我,道長(zhǎng)官册,這世上最難降的妖魔是什么生兆? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 60,294評(píng)論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮攀隔,結(jié)果婚禮上皂贩,老公的妹妹穿的比我還像新娘。我一直安慰自己昆汹,他們只是感情好明刷,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,295評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著满粗,像睡著了一般辈末。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上映皆,一...
    開(kāi)封第一講書(shū)人閱讀 52,874評(píng)論 1 314
  • 那天挤聘,我揣著相機(jī)與錄音,去河邊找鬼捅彻。 笑死组去,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的步淹。 我是一名探鬼主播从隆,決...
    沈念sama閱讀 41,285評(píng)論 3 424
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼诚撵,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了键闺?” 一聲冷哼從身側(cè)響起寿烟,我...
    開(kāi)封第一講書(shū)人閱讀 40,249評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎辛燥,沒(méi)想到半個(gè)月后筛武,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,760評(píng)論 1 321
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡挎塌,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,840評(píng)論 3 343
  • 正文 我和宋清朗相戀三年徘六,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片勃蜘。...
    茶點(diǎn)故事閱讀 40,973評(píng)論 1 354
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡硕噩,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出缭贡,到底是詐尸還是另有隱情炉擅,我是刑警寧澤,帶...
    沈念sama閱讀 36,631評(píng)論 5 351
  • 正文 年R本政府宣布阳惹,位于F島的核電站谍失,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏莹汤。R本人自食惡果不足惜快鱼,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,315評(píng)論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望纲岭。 院中可真熱鬧抹竹,春花似錦、人聲如沸止潮。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,797評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)喇闸。三九已至袄琳,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間燃乍,已是汗流浹背唆樊。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,926評(píng)論 1 275
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留刻蟹,地道東北人逗旁。 一個(gè)月前我還...
    沈念sama閱讀 49,431評(píng)論 3 379
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像舆瘪,于是被迫代替她去往敵國(guó)和親痢艺。 傳聞我的和親對(duì)象是個(gè)殘疾皇子仓洼,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,982評(píng)論 2 361

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

  • 前言 本文為對(duì)Java泛型技術(shù)類(lèi)型擦除部分的一個(gè)總結(jié),主要參考文獻(xiàn)有《Java編程思想 第4版》堤舒、《Java核心技...
    開(kāi)發(fā)者小王閱讀 20,383評(píng)論 3 40
  • 最近在看 Rxjava 與 Retrofit ,發(fā)現(xiàn)它們都大量的使用到了泛型這個(gè)概念哺呜,之前我對(duì)泛型是有一點(diǎn)了解的舌缤,...
    張光光閱讀 1,312評(píng)論 4 10
  • 對(duì)于我們java中的泛型,可能很多人知道怎么使用并且使用的還不錯(cuò)某残,但是我認(rèn)為想要恰到好處的使用泛型国撵,還是需要深入的...
    Single_YAM閱讀 585評(píng)論 0 5
  • 泛型是Java 1.5引入的新特性。泛型的本質(zhì)是參數(shù)化類(lèi)型玻墅,這種參數(shù)類(lèi)型可以用在類(lèi)介牙、變量、接口和方法的創(chuàng)建中澳厢,分別...
    何時(shí)不晚閱讀 3,040評(píng)論 0 2
  • 記得小時(shí)候的我還是個(gè)瘦子环础,那個(gè)時(shí)候小學(xué)六年級(jí)的我,身高160剩拢,體重78线得,完全不胖啊,但是還是有人說(shuō)我胖徐伐。 ...
    yana0714閱讀 267評(píng)論 0 1