Java 泛型通配符上下界理解及應(yīng)用

一.通配符的應(yīng)用

實(shí)踐檢驗(yàn)真理狂窑,所以在說(shuō)明通配符上下界的理解的時(shí)候垛玻,先說(shuō)明下什么時(shí)候使用通配符

關(guān)于泛型
類(lèi)型通配符的作用是為了代替泛型類(lèi)的類(lèi)型實(shí)參滥搭。

當(dāng)我們使用泛型類(lèi)作為參數(shù)時(shí)何什,我們不想固定具體的泛型類(lèi)型實(shí)參,而是想接收任意類(lèi)型咖楣,或者某個(gè)類(lèi)及其子類(lèi)或超類(lèi)類(lèi)型作為類(lèi)型實(shí)參督笆,這個(gè)時(shí)候就需要使用通配符了,使用泛型類(lèi)<?>作為類(lèi)型實(shí)參
總結(jié)來(lái)說(shuō)通配符解決的問(wèn)題就是:類(lèi)B是類(lèi)A子類(lèi)诱贿,但是泛型類(lèi)<B>不是泛型類(lèi)<A>的子類(lèi)娃肿,但是我們又想有這么個(gè)類(lèi)型能同時(shí)接收泛型類(lèi)<B>泛型類(lèi)<A>類(lèi)型作為參數(shù)的問(wèn)題

通配符類(lèi)型

  • 無(wú)邊界通配符:<?>
    使用無(wú)邊界通配符可以讓泛型接收任意類(lèi)型的數(shù)據(jù)

  • 上邊界通配符 :<?extends 具體類(lèi)型 >
    使用固定上邊界的通配符的泛型可以接收指定類(lèi)型及其所有子類(lèi)類(lèi)型的數(shù)據(jù)珠十,這里的指定類(lèi)型可以是類(lèi)也可以是接口

  • 下邊界通配符 :<? spuer 具體類(lèi)型>
    所有固定下邊界的通配符的泛型可以接收指定類(lèi)型及其所有超類(lèi)類(lèi)型的數(shù)據(jù)料扰。

通配符無(wú)法同時(shí)指定上下邊界

舉個(gè)栗子
我們常用的List就是一個(gè)泛型類(lèi),以java.lang.Number類(lèi)及其子類(lèi)焙蹭,超類(lèi)作為類(lèi)型實(shí)參晒杈,具體繼承關(guān)系如下:


看下下面這段代碼:

private List<? extends Number> data;

    private void test() {
        List<Number> numbers = new ArrayList<>();
        List<Integer> integers = new ArrayList<>();
        //List<Number> data = integers; //編譯報(bào)錯(cuò)
        data = numbers;
        data = integers;
    }

顯然雖然IntegerNumber的子類(lèi),但是List<Integer>并不是List<Number>的子類(lèi)孔厉,所以List<Integer>類(lèi)型的變量不能直接賦值給List<Number>的變量拯钻。這時(shí)候通配符就起到作用了List<? extends Number>可以看做是List<Integer>List<Number>的父類(lèi)型,它可以接收Number類(lèi)或者其子類(lèi)型作為類(lèi)型形參的泛型數(shù)據(jù)烟馅。
所以當(dāng)我們要在一個(gè)方法或者類(lèi)中接收不固定類(lèi)型實(shí)參的泛型數(shù)據(jù)说庭,可以考慮使用通配符

二.關(guān)于通配符的上下界

1. 無(wú)邊界 和 上邊界通配符

使用無(wú)邊界和上邊界通配符的泛型不能賦值(除了null)然磷,可以取值郑趁,但是只能去指定的類(lèi)型及其超類(lèi)類(lèi)型(無(wú)邊界只能取Object類(lèi)型數(shù)據(jù))

(無(wú)邊界其實(shí)上邊界就是Object)

List為例:下面這段代碼當(dāng)我們用List<?>或者List<? extends Number>add數(shù)據(jù)時(shí)發(fā)現(xiàn)都會(huì)編譯報(bào)錯(cuò)。
為什么:根據(jù)上面應(yīng)用的結(jié)論姿搜,List<Integer>寡润、List<Long>捆憎、List<Double>這些類(lèi)型可以理解為List<?>或者List<? extends Number>的子類(lèi)型。
這時(shí)候List<?>或者List<? extends Number> add時(shí)候不知道到底要往List<Integer>梭纹、List<Long>躲惰、List<Double>還是其他Number子類(lèi)型的Listadd數(shù)據(jù)的是IntegerLong還是Double類(lèi)型变抽。這么操作可能會(huì)引發(fā)類(lèi)型不一致的問(wèn)題础拨,這顯然和泛型的設(shè)計(jì)是相悖的。因此Java為了保證類(lèi)型一致绍载,是不允許這么操作的诡宗。但是null是所有引用類(lèi)型都有元素,所有可以add成功击儡。

List<?> data = new ArrayList<>();
List<?> data = new ArrayList<>();
data.add(new Object()); //編譯報(bào)錯(cuò)
data.add(10);  //編譯報(bào)錯(cuò)
data.add(null);

 List<? extends Number> numbers = new ArrayList<>();
numbers.add(10); //編譯報(bào)錯(cuò)
numbers.add(new BigDecimal(20)); //編譯報(bào)錯(cuò)
numbers.add(null);

在看一下get取值方法:
下面代碼可以看出(忽略運(yùn)行錯(cuò)誤啊塔沃,只是為了說(shuō)明泛型編譯問(wèn)題):get方法是可以取到指定類(lèi)型及其超類(lèi)型的數(shù)據(jù)。

List<?> data = new ArrayList<>();
Object object = data.get(0);

List<? extends Number> numbers = new ArrayList<>();
Number number = numbers.get(0);
Object number2 = numbers.get(0);
2.下邊界通配符

與無(wú)邊界和上邊界通配符相反阳谍,下邊界通配符只能取Object類(lèi)型的數(shù)據(jù)蛀柴,但可以賦值,只要是指定類(lèi)型或者其子類(lèi)型都能成功賦值

還是以List類(lèi)為例矫夯,代碼如下鸽疾,對(duì)應(yīng)到List里面就是add指定類(lèi)型及其子類(lèi)型數(shù)據(jù)時(shí)可以正常編譯通過(guò),但是get方法不能編譯通過(guò)
為什么:因?yàn)?code>Long训貌、BigDecimal肮韧、Float都是Numer的子類(lèi),根據(jù)之前的結(jié)論? super Number代表可以接收指定類(lèi)型及其父類(lèi)型的數(shù)據(jù)旺订,所以List<? super Number>可以理解為List<Number>或者List<Object>的父類(lèi)型弄企,顯然List<Number>或者List<Object>是可以add Numer的子類(lèi)型數(shù)據(jù)的。但是get的時(shí)候因?yàn)椴恢谰唧w是
List<Number>還是List<Object>或者是之間的什么類(lèi)型区拳,所以只能get所以類(lèi)型的父類(lèi)型Object`類(lèi)型

List<? super Number> data = new ArrayList<>();
data.add(10);
data.add(new BigDecimal(1000));
data.add(10.07f);
data.add(new Object()) //編譯報(bào)錯(cuò)

Object object = data.get(0);
Number number = data.get(0); //編譯報(bào)錯(cuò)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末拘领,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子樱调,更是在濱河造成了極大的恐慌约素,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,123評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件笆凌,死亡現(xiàn)場(chǎng)離奇詭異圣猎,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)乞而,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門(mén)送悔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事欠啤〖栽澹” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,723評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵洁段,是天一觀的道長(zhǎng)应狱。 經(jīng)常有香客問(wèn)我,道長(zhǎng)祠丝,這世上最難降的妖魔是什么疾呻? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,357評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮写半,結(jié)果婚禮上罐韩,老公的妹妹穿的比我還像新娘。我一直安慰自己污朽,他們只是感情好散吵,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,412評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著蟆肆,像睡著了一般矾睦。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上炎功,一...
    開(kāi)封第一講書(shū)人閱讀 49,760評(píng)論 1 289
  • 那天枚冗,我揣著相機(jī)與錄音,去河邊找鬼蛇损。 笑死赁温,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的淤齐。 我是一名探鬼主播股囊,決...
    沈念sama閱讀 38,904評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼更啄!你這毒婦竟也來(lái)了稚疹?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,672評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤祭务,失蹤者是張志新(化名)和其女友劉穎内狗,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體义锥,經(jīng)...
    沈念sama閱讀 44,118評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡柳沙,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,456評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了拌倍。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片赂鲤。...
    茶點(diǎn)故事閱讀 38,599評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡噪径,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蛤袒,到底是詐尸還是另有隱情熄云,我是刑警寧澤膨更,帶...
    沈念sama閱讀 34,264評(píng)論 4 328
  • 正文 年R本政府宣布妙真,位于F島的核電站,受9級(jí)特大地震影響荚守,放射性物質(zhì)發(fā)生泄漏珍德。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,857評(píng)論 3 312
  • 文/蒙蒙 一矗漾、第九天 我趴在偏房一處隱蔽的房頂上張望锈候。 院中可真熱鬧,春花似錦敞贡、人聲如沸泵琳。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,731評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)获列。三九已至,卻和暖如春蛔垢,著一層夾襖步出監(jiān)牢的瞬間击孩,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,956評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工鹏漆, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留巩梢,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,286評(píng)論 2 360
  • 正文 我出身青樓艺玲,卻偏偏與公主長(zhǎng)得像括蝠,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子饭聚,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,465評(píng)論 2 348

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