您好,登錄后才能下訂單哦!
本篇內容介紹了“Java泛型的通配符有哪些”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
一句話說就是類型參數化。什么意思呢?參數化的意思就是我們在定義的時候不知道具體的值,我們在到我們實際運行的時候才知道具體的值。類型參數化就是具體類型在定義的時候不知道,在實際運行的時候是確定的某一個類型。
泛型是很多高級語言都有的特性。根據定義,泛型在運行時表示同一個類型,我們比較容易想到 List<A>
和 List<B>
用 2 個不同的 Class 表示,這個是可行的,但是 Java 由于需要兼容支持舊的代碼,而且在推出泛型前就提供了容器類,這種方式(List<A>
和 List<B>
用 2 個不同的 Class)無法兼容以前的老代碼,所以這個實現方法不適用。所以 Java 大佬們想了另外一種方式來實現泛型,這種方式就是類型擦除
。
類型擦除就是在實際生成字節碼的時候,編譯器源碼里面定義的 List<A>
變成了 List<Object>
,源碼里面定義的 A Class
被擦除
了,變成了 Object
,同時在使用的時候,會強制類型轉換,把取出來的 object
轉成 A
的實例去使用。這就是類型擦除。
初步看,泛型擦除好像是沒什么大的問題,但是仔細想想,在強制類型轉換的時候,由于會丟掉類型的一些信息,會導致一些不符合預期的事情。比如有個基類 A,和它的兩個子類 B 和 C ,然后我們有下面的一段代碼。
List<A> listA = new ArrayList<A>(); listA.add(new B()); // 錯誤的,
第二行代碼是不符合預期的,因為 listA
里面期望放的是 A
而不是 B
。 但是這個好像不太符合預期,我們有時候希望子類是可以放進容器里面的。但是如果支持這個操作的話,會發生什么呢?取出來來的是 B
還是 C
?如果不能明確,那么就沒有實現“泛型”。
為了解決這個問題, Java 大佬們想了個方法,提出了一些通配符來解決這些問題。
?
、extends
和 super
在理解通配符之前,我們需要知道的是,通配符的發明是為了解決什么問題?至少要解決的一個問題是:容器里面放進去的是什么,取出來的就是什么。
這個問題,其實分兩步,放進去,是說放進去同一種類型的東西。取出來,是說取出同一種類型的東西。或者說,用到通配符的地方應該是在不同的地方,一個地方把數據寫到容器,另外一個地方把數據從容器拿出來,如果實在同一個代碼塊里寫入和讀取數據到同一個容器,應該是知道具體類型的,是不需要用到通配符的。
?
通配符?
通配符稱為無限通配符,表示不確定或者不關心類型。
一般稱為上界通配符,表示的意思是:取值范圍為 (某個類的子類, 某個類]。再想想我們之前說的,通配符要解決的問題?放進去的是什么,取出來的就應該是什么。放數據和取數據應用在不同的場景。如果我們在同一個場景,就不需要用到通配符了,因為類型是已知的。
通過上面的表述,容易推斷出來 <? extends E>
的集合只能往外拿數據,因為取出來的一定是 E
,但是放進去的不知道是什么,可能是 E
,也可能是 E
的子類,如果允許往集合里面放東西,就不能保證放進去的是什么,拿出來的就是什么了。因為只能保證拿出來的是 E
。
這個特性也叫做協變。
一般稱為下界通配符,表示的意思是:取值范圍為 [某個類,這個類的父類)。結合上面小節的解釋,可以推斷出 <? super S>
的集合只能往里面放數據,而不能從里面拿東西,為什么呢?因為 <? extends E>
解決的就是拿出來的問題啊,所以這個解決的就是放進去的問題啊,囧。里面放的是下限或者下限的子類。
這個特性也叫做逆變。
“Java泛型的通配符有哪些”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。