通配符及泛型的若干問題

廢話不多說,直接進入正題。

2個概念 上限通配符 及下限通配符

下面我們看一個程序:


215256386.jpg


上限通配符(<? extends Object>)

下限通配符 (<? super Integer>)


說實話,這些概念確實讓人很頭痛,如果不是那種要去應對考試的,我覺得根本沒必要記,知道怎麼用就好了,那麼接下來 我就幫大家分析下上面出錯的原因,讓大家更好的理解。


首先看第8行 泛型是<? extends Object>,這個要怎麼理解呢?看了一下網上的資料,覺得好難懂,好吧,可能是我智商被壓制了。下面我就用我自己理解的,比較簡單的話來講。其實你可以這麼理解

他就相當於<?>(?代表任意的一個類) 但是 他給?加了一個條件,就是這個類必須要繼承Object,

這時,有人就會問,不是所有類都繼承Object這個類嗎,那不是所有的類的實例都可以add進來嗎沒爲什麼第9,10,11行還會報錯呢?恩,當時我也是這麼想的,所以悶了好久,然後又想了一下,想通了。

舉個例子,我們把?用Integer替換,是不是滿足 ? extends Object,那麼我們接下來add(new String("asd"));往list1裏面加個字符串可以嘛?顯然是不可以的。那麼String是不是extends Object呢?是的。

所以我們跟本不知道?是代表什麼,所以我們可以用各種類去替換“?”,從而排除了任何類的實例都是無法add進list1裏面的。所以第9,10,11行出錯。

下面我們可以想下,什麼能夠傳入呢?沒錯,就是null,不管你是什麼類型,你肯定是一個類型,我add 一個null進list1是任何情況下都不會出錯的。

下面我們可以說一下取的情況,也就是第13,14,15行代碼。


因爲我們無法判斷?是什麼,所以我們無法準確的給他一個類型。但是我們知道他的父類是Object,那麼直接用Object定義一個變量 當然能存放取出來的對象。



至於下限通配符其實也差不多的。


<? super Integer>


可以用我上面的方式來判斷,先用<?>來代替<? super Integer>,然後想,?其實是被加了一個限定條件的,限定條件是:是Integer這個類的父類。

如果你熟練的話,直接解讀<? super Integer>,傳入的參數必須是Integer的符類型,但是Integer的父類型有很多,所以我們根本不能確定是哪個,但是我們能確定的是,他是Integer的父類,所以你可以add一個Integer實例進list2中。

在接收的時候,我們依然無法準確判斷?是哪個類,但我們知道的是他肯定是Object的子類,所以定義一個Object引用變量指向這個取出來的類,這樣當然是可以的。



還有一個關鍵問題是new ArrayList<?>();中 ? 填的是什麼呢。

首先 你不能直接用“?”,或者<? extends Object>這種有通配符的標記,會報錯的。


然後就是 你填的應該是一個具體的類名,但是你這個類名必須要滿足你前面那個約束。

比如 第8行 String是滿足<? extends Object>這個的 因爲String是繼承Object的。


還有就是,如果你前面是一個具體的類,那麼你後面必須是與前面相同的具體的類,不能是他的子類,更不能是其他類。


說的有點多,雖然儘量用很通俗的語言了,但是可能還是有疑問的話請給我留言。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章