從屌絲到架構(gòu)師的飛越(集合篇)-泛型

一.介紹

泛型在java中有很重要的地位炸茧,在面向?qū)ο缶幊碳案鞣N設(shè)計模式中有非常廣泛的應用腻豌。

什么是泛型潮酒?為什么要使用泛型怠缸?

泛型桥爽,即“參數(shù)化類型”译蒂。一提到參數(shù)被饿,最熟悉的就是定義方法時有形參彩掐,然后調(diào)用此方法時傳遞實參医咨。那么參數(shù)化類型怎么理解呢枫匾?顧名思義,就是將類型由原來的具體的類型參數(shù)化拟淮,類似于方法中的變量參數(shù)干茉,此時類型也定義成參數(shù)形式(可以稱之為類型形參),然后在使用/調(diào)用時傳入具體的類型(類型實參)很泊。

泛型的本質(zhì)是為了參數(shù)化類型(在不創(chuàng)建新的類型的情況下角虫,通過泛型指定的不同類型來控制形參具體限制的類型)沾谓。也就是說在泛型使用過程中,操作的數(shù)據(jù)類型被指定為一個參數(shù)戳鹅,這種參數(shù)類型可以用在類均驶、接口和方法中,分別被稱為泛型類枫虏、泛型接口妇穴、泛型方法。

二.知識點介紹

1隶债、泛型的由來

2腾它、泛型使用

3、泛型聲明

三.上課對應視頻的說明文檔

1死讹、泛型的由來

先看一個案例:

List arrayList = new ArrayList();

arrayList.add("aaaa");

arrayList.add(100);

for(int i = 0; i< arrayList.size();i++){

String item = (String)arrayList.get(i);

System.out.printf("泛型測試","item = " + item);

}

運行結(jié)果:

java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String

ArrayList可以存放任意類型瞒滴,例子中添加了一個String類型,添加了一個Integer類型回俐,再使用時都以String的方式使用逛腿,因此程序崩潰了。為了解決類似這樣的問題(在編譯階段就可以解決)仅颇,泛型應運而生单默。

2、泛型的使用

泛型有三種使用方式忘瓦,分別為:泛型類搁廓、泛型接口、泛型方法

2.1耕皮、泛型類

泛型類型用于類的定義中境蜕,被稱為泛型類。通過泛型可以完成對一組類的操作對外開放相同的接口凌停。最典型的就是各種容器類粱年,如:List、Set罚拟、Map台诗。

泛型類的最基本寫法(這么看可能會有點暈,會在下面的例子中詳解)格式:

class 類名稱 <泛型標識:可以隨便寫任意標識號赐俗,標識指定的泛型的類型>{

private 泛型標識 /*(成員變量類型)*/ var;

.....

}

}

代碼示例:

//此處T可以隨便寫為任意標識拉队,常見的如T、E阻逮、K粱快、V等形式的參數(shù)常用于表示泛型

//在實例化泛型類時,必須指定T的具體類型

public class Generic<T>{

//key這個成員變量的類型為T,T的類型由外部指定?

private T key;

public Generic(T key) { //泛型構(gòu)造方法形參key的類型也為T,T的類型由外部指定

this.key = key;

}

public T getKey(){ //泛型方法getKey的返回值類型為T事哭,T的類型由外部指定

return key;

}

}

public class Test{

public static void main(String args[]){

//泛型的類型參數(shù)只能是類類型(包括自定義類)漫雷,不能是簡單類型

//傳入的實參類型需與泛型的類型參數(shù)類型相同,即為Integer.

Generic<Integer> genericInteger = new Generic<Integer>(123456);

//傳入的實參類型需與泛型的類型參數(shù)類型相同慷蠕,即為String.

    Generic<String> genericString = new Generic<String>("key_vlaue");

  ? System.out.println("泛型測試 : key is " + genericInteger.getKey());

System.out.println("泛型測試 : key is " + genericString.getKey());

}

}

//運行結(jié)果:

泛型測試: key is 123456

泛型測試: key is key_vlaue

2.2珊拼、泛型接口

泛型接口與泛型類的定義及使用基本相同。泛型接口常被用在各種類的生產(chǎn)器中:

代碼示例:

//定義一個泛型接口

public interface Generator<T> {

public T next();

}

/**

* 未傳入泛型實參時流炕,與泛型類的定義相同澎现,在聲明類的時候,需將泛型的聲明也一起加到類中

* 即:class FruitGenerator<T> implements Generator<T>{

* 如果不聲明泛型每辟,如:class FruitGenerator implements Generator<T>剑辫,編譯器會報錯:"Unknown class"

*/

class FruitGenerator<T> implements Generator<T>{

@Override

public T next() {

return null;

}

}

/**

* 傳入泛型實參時:

* 定義一個生產(chǎn)器實現(xiàn)這個接口,雖然我們只創(chuàng)建了一個泛型接口Generator<T>

* 但是我們可以為T傳入無數(shù)個實參,形成無數(shù)種類型的Generator接口渠欺。

* 在實現(xiàn)類實現(xiàn)泛型接口時妹蔽,如已將泛型類型傳入實參類型,則所有使用泛型的地方都要替換成傳入的實參類型

* 即:Generator<T>挠将,public T next();中的的T都要替換成傳入的String類型胳岂。

*/

public class FruitGenerator implements Generator<String> {

private String[] fruits = new String[]{"Apple", "Banana", "Pear"};

@Override

public String next() {

Random rand = new Random();

return fruits[rand.nextInt(3)];

}

}

2.3、泛型方法

在java中,泛型類的定義非常簡單舔稀,但是泛型方法就比較復雜了乳丰。

尤其是我們見到的大多數(shù)泛型類中的成員方法也都使用了泛型,有的甚至泛型類中也包含著泛型方法内贮,這樣在初學者中非常容易將泛型方法理解錯了产园。

泛型類,是在實例化類的時候指明泛型的具體類型夜郁;泛型方法什燕,是在調(diào)用方法的時候指明泛型的具體類型 。

代碼示例:

public class GenericTest {

//這個類是個泛型類竞端,在上面已經(jīng)介紹過

public class Generic<T>{? ?

private T key;

public Generic(T key) {

this.key = key;

}

//我想說的其實是這個屎即,雖然在方法中使用了泛型,但是這并不是一個泛型方法事富。

//這只是類中一個普通的成員方法剑勾,只不過他的返回值是在聲明泛型類已經(jīng)聲明過的泛型。

//所以在這個方法中才可以繼續(xù)使用 T 這個泛型赵颅。

public T getKey(){

return key;

}

}

/**

* 這才是一個真正的泛型方法。

* 首先在public與返回值之間的<T>必不可少暂刘,這表明這是一個泛型方法饺谬,并且聲明了一個泛型T

* 這個T可以出現(xiàn)在這個泛型方法的任意位置.

* 泛型的數(shù)量也可以為任意多個

*? ? 如:public <T,K> K showKeyName(Generic<T> container){

*? ? ? ? ...

*? ? ? ? }

*/

public <T> T showKeyName(Generic<T> container){

System.out.println("container key :" + container.getKey());

//當然這個例子舉的不太合適,只是為了說明泛型方法的特性。

T test = container.getKey();

return test;

}

public static void main(String[] args) {

}

}

代碼示例2:

public class Main {

public static <T> void out(T t) {

System.out.println(t);

}

public static void main(String[] args) {

out("findingsea");

out(123);

out(11.11);

out(true);

}

}

public class Main {

public static <T> void out(T... args) {

for (T t : args) {

System.out.println(t);

}

}

public static void main(String[] args) {

out("findingsea", 123, 11.11, true);

}

}

代碼示例3:

public class GenericFruit {

public static void main(String[] args) {

Apple apple = new Apple();

Person person = new Person();

GenerateTest<Fruit> generateTest = new GenerateTest<Fruit>();

//apple是Fruit的子類募寨,所以這里可以

generateTest.show_1(apple);

//編譯器會報錯族展,因為泛型類型實參指定的是Fruit,而傳入的實參類是Person

//generateTest.show_1(person);

//使用這兩個方法都可以成功

generateTest.show_2(apple);

generateTest.show_2(person);

//使用這兩個方法也都可以成功

generateTest.show_3(apple);

generateTest.show_3(person);

}

}

class Fruit{

@Override

public String toString() {

return "fruit";

}

}

class Apple extends Fruit{

@Override

public String toString() {

return "apple";

}

}

class Person{

@Override

public String toString() {

return "Person";

}

}

class GenerateTest<T>{

public void show_1(T t){

System.out.println(t.toString());

}

//在泛型類中聲明了一個泛型方法拔鹰,使用泛型E仪缸,這種泛型E可以為任意類型×兄可以類型與T相同恰画,也可以不同。

//由于泛型方法在聲明的時候會聲明泛型<E>瓷马,因此即使在泛型類中并未聲明泛型拴还,編譯器也能夠正確識別泛型方法中識別的泛型。

public <E> void show_3(E t){

System.out.println(t.toString());

}

//在泛型類中聲明了一個泛型方法欧聘,使用泛型T片林,注意這個T是一種全新的類型,可以與泛型類中聲明的T不是同一種類型怀骤。

public <T> void show_2(T t){

System.out.println(t.toString());

}

}

3费封、泛型的聲明

可以用<T>、<K,V>蒋伦、<T? extends? Number>等進行泛型的聲明弓摘。其中,<T? extends? Number>的聲明方式限定了T的范圍凉敲,T只能為 Number的子類衣盾。

如:

E – Element (在集合中使用,因為集合中存放的是元素)

T – Type(Java 類)

K – Key(鍵)

V – Value(值)

N – Number(數(shù)值類型)

爷抓? – 表示不確定的java類型(無限制通配符類型)

Object – 是所有類的根類势决,任何類的對象都可以設(shè)置給該Object引用變量,使用的時候可能需要類型強制轉(zhuǎn)換蓝撇,但是用使用了泛型T果复、E等這些標識符后,在實際用之前類型就已經(jīng)確定了渤昌,不需要再進行類型強制轉(zhuǎn)換虽抄。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市独柑,隨后出現(xiàn)的幾起案子迈窟,更是在濱河造成了極大的恐慌,老刑警劉巖忌栅,帶你破解...
    沈念sama閱讀 219,270評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件车酣,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機湖员,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評論 3 395
  • 文/潘曉璐 我一進店門贫悄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人娘摔,你說我怎么就攤上這事窄坦。” “怎么了凳寺?”我有些...
    開封第一講書人閱讀 165,630評論 0 356
  • 文/不壞的土叔 我叫張陵鸭津,是天一觀的道長。 經(jīng)常有香客問我读第,道長曙博,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,906評論 1 295
  • 正文 為了忘掉前任怜瞒,我火速辦了婚禮父泳,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘吴汪。我一直安慰自己惠窄,他們只是感情好,可當我...
    茶點故事閱讀 67,928評論 6 392
  • 文/花漫 我一把揭開白布漾橙。 她就那樣靜靜地躺著杆融,像睡著了一般。 火紅的嫁衣襯著肌膚如雪霜运。 梳的紋絲不亂的頭發(fā)上脾歇,一...
    開封第一講書人閱讀 51,718評論 1 305
  • 那天,我揣著相機與錄音淘捡,去河邊找鬼藕各。 笑死,一個胖子當著我的面吹牛焦除,可吹牛的內(nèi)容都是我干的激况。 我是一名探鬼主播,決...
    沈念sama閱讀 40,442評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼膘魄,長吁一口氣:“原來是場噩夢啊……” “哼乌逐!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起创葡,我...
    開封第一講書人閱讀 39,345評論 0 276
  • 序言:老撾萬榮一對情侶失蹤浙踢,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后灿渴,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體成黄,經(jīng)...
    沈念sama閱讀 45,802評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡呐芥,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,984評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了奋岁。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,117評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡荸百,死狀恐怖闻伶,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情够话,我是刑警寧澤蓝翰,帶...
    沈念sama閱讀 35,810評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站女嘲,受9級特大地震影響畜份,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜欣尼,卻給世界環(huán)境...
    茶點故事閱讀 41,462評論 3 331
  • 文/蒙蒙 一爆雹、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧愕鼓,春花似錦钙态、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至磺送,卻和暖如春驻子,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背估灿。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評論 1 272
  • 我被黑心中介騙來泰國打工崇呵, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人甲捏。 一個月前我還...
    沈念sama閱讀 48,377評論 3 373
  • 正文 我出身青樓演熟,卻偏偏與公主長得像,于是被迫代替她去往敵國和親司顿。 傳聞我的和親對象是個殘疾皇子芒粹,可洞房花燭夜當晚...
    茶點故事閱讀 45,060評論 2 355

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