這篇我們講泛型惯驼。講ArrayList或是Hashmap的時(shí)候有些人注意到寫聲明語句時(shí)下面會(huì)有黃色的波浪線墓臭,把鼠標(biāo)移到那兒男公,可以看到它說是個(gè)raw type豁鲤,應(yīng)該添加generic type或链。
Raw的意思是原始的惫恼,沒有修飾的。啥意思呢澳盐?之前說過祈纯,ArrayList就像個(gè)大麻袋,里面可以裝很多不同類型的變量或是對(duì)象叼耙,如果我現(xiàn)在把麻袋口一封腕窥,你知道我麻袋里裝的是什么類型的東西么?你不知道∩竿瘢現(xiàn)在這個(gè)raw就相當(dāng)于我直接把麻袋一封簇爆,啥都不告訴你,是個(gè)最原始的狀態(tài)爽撒。那generic type呢入蛆?它的意思就是泛型,就相當(dāng)于我在封好的麻袋口貼的一張標(biāo)簽硕勿,告訴你這里面是什么哨毁。以ArrayList為例,假設(shè)我里面裝的都是字符串類型的元素源武,我就可以給它加個(gè)字符串類型的標(biāo)簽:
如果你的ArrayList里只有String類型的元素扼褪,那你會(huì)發(fā)現(xiàn)小黃線馬上就不見了想幻,因?yàn)橛袠?biāo)簽了,ArrayList知道它里面裝的是什么:
我再聲明一個(gè)ArrayList, 把標(biāo)簽改成Integer话浇,你就會(huì)發(fā)現(xiàn)雖然它也是ArrayList脏毯,可是這個(gè)麻袋現(xiàn)在只能裝整型了,你如果還繼續(xù)裝字符串就錯(cuò)了:
提示你整型ArrayList不接受字符串幔崖。注意食店,標(biāo)簽里整型寫Integer,不能寫int岖瑰。如果你的ArrayList里什么類型都想裝怎么辦呢叛买?好辦,直接用Object當(dāng)標(biāo)簽唄蹋订,因?yàn)樵趈ava里所有的類都繼承自O(shè)bject類,自然也就都屬于它刻伊。這點(diǎn)我們也在講多態(tài)時(shí)提過:
加了標(biāo)簽的對(duì)象就叫作泛型露戒。你知道泛指是什么意思吧?就是廣泛地指定捶箱,非特指智什。這里面是一個(gè)意思。還有丁屎,這個(gè)標(biāo)簽看起來是不是像方法里的參數(shù)荠锭?只不過用尖括號(hào)而不是圓括號(hào)。所以我們又給這個(gè)標(biāo)簽起了一個(gè)更形象的名字 – 參數(shù)化類型晨川。并不是所有的類初始化時(shí)都可以加參數(shù)化類型证九,上面例子中的ArrayList之所以允許加參數(shù)化類型,因?yàn)閖ava文檔上允許:
看見那個(gè)尖括號(hào)E了嗎共虑?它可以代表任意類型愧怜。所以,當(dāng)我用某一個(gè)標(biāo)簽來初始化一個(gè)對(duì)象時(shí)妈拌,比如ArrayList<String> al = new ArrayList<String>()拥坛,這個(gè)E就代表String。
既然可以用基本類型當(dāng)標(biāo)簽尘分,必然也可以用引用類型當(dāng)標(biāo)簽猜惋。看下面程序:
泛型可以直接告訴你它里邊裝的是什么類型培愁,一目了然著摔。泛型還有一個(gè)優(yōu)點(diǎn),不用強(qiáng)制轉(zhuǎn)換竭钝。之前討論ArrayList和Hashmap時(shí)說過梨撞,從集合里拿元素的時(shí)候必須強(qiáng)制轉(zhuǎn)換:
大家都是人腦雹洗,人腦都比電腦聰明,我們知道ArrayList里面就是Food類型的東西卧波,我用get方法查看一下取出來的肯定是Food類型的时肿,可不加泛型的ArrayList它就是不知道,它只能識(shí)別它是個(gè)object港粱,它就是笨螃成。所以你要強(qiáng)轉(zhuǎn)〔槠海可加了泛型就不用強(qiáng)轉(zhuǎn)了:
剛才演示的是泛型用在ArrayList的情況寸宏。大家知道,ArrayList是java自帶的引用類型偿曙,那泛型是不是也可以用在自己創(chuàng)建的類上呢氮凝?沒問題,而且格式也是一樣的:
比如我現(xiàn)在自己創(chuàng)建一個(gè)叫TypeBag的類望忆,那我可以這么寫:
E換成別的字符也行罩阵,其實(shí)它就好比是一個(gè)形參一樣。聲明完TypeBag類后就可以在主函數(shù)里用泛型初始化對(duì)象了启摄。和一般參數(shù)一樣稿壁,泛型也可以擁有好幾個(gè)參數(shù)化類型。比如看我下面的例子:
如果不把泛型算進(jìn)去歉备,這個(gè)小程序應(yīng)該所有人都看得懂了傅是,沒什么難度。但TypeBag里接了兩個(gè)泛型參數(shù)Integer和String蕾羊,中間用逗號(hào)隔開喧笔,正好對(duì)應(yīng)TypeBag里的K和V。雖然TypeBag類不再像ArrayList是個(gè)麻袋那樣形象肚豺,但它的泛型依然像標(biāo)簽一樣起到了提示的作用溃斋。這里它明確指示初始化時(shí)需要傳參數(shù),并且第一個(gè)是Integer吸申,第二個(gè)是String梗劫。
再說最后一個(gè)例子,TypeBag類里面放引用類型截碴。比如我是個(gè)賣電腦的梳侨,我想把產(chǎn)品都打印出來。先寫程序再講解:
這里面除了主類外我又聲明了兩個(gè)類日丹,一個(gè)是Computer類走哺,還一個(gè)是TypeBag類。當(dāng)我執(zhí)行TypeBag<Computer> t1 = new TypeBag<Computer>()時(shí)哲虾,把TypeBag這個(gè)類貼上了一個(gè)Computer類的標(biāo)簽丙躏,明確提示我這個(gè)TypeBag類與Computer類相綁定:
所以择示,接下來執(zhí)行t1.setType(asus)為type變量賦值,結(jié)果其實(shí)就是type = asus晒旅。而asus存的是一個(gè)Computer對(duì)象的地址栅盲,意味著t1也存有該對(duì)象的地址:
所以,經(jīng)過貼標(biāo)簽綁定后废恋,TypeBag和Computer本質(zhì)上成為了同一個(gè)類谈秫。打印時(shí),t1.getType()得到的當(dāng)然就是asus鱼鼓,asus再訪問自己的成員變量最后一起打印出來拟烫。t2和t3同理。
這就是泛型的一些基本概念迄本,最后一個(gè)例子可能理解起來需要點(diǎn)時(shí)間硕淑,別的應(yīng)該沒什么問題。講selenium自動(dòng)化測(cè)試的時(shí)候我們會(huì)用到ArrayList嘉赎,到時(shí)我就會(huì)把泛型帶上喜颁,所以請(qǐng)大家好好復(fù)習(xí)。
這篇文章的源代碼是ArrayListGeneric曹阔,SelfClassBasicGeneric和SelfClassRefGeneric這三個(gè)小項(xiàng)目啊送,再鞏固一下码泛。集合到此就暫時(shí)告一段落,下篇文章我們開始講java的另一個(gè)重要概念 - 文件的操作铜秆。
本篇知識(shí)點(diǎn)及注意事項(xiàng):
1. 泛型又叫參數(shù)化類型奢米,可以顯式告訴你綁定的是什么類型的元素抓韩,既可以是基本類型也可以是復(fù)雜類型。
2. 泛型不用強(qiáng)制轉(zhuǎn)換鬓长。
3. 可以自己定義一個(gè)泛型類谒拴,然后綁定其他類。