<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
比如,我們現在定義:List<? extends T>首先你很容易誤解它為繼承於T的所有類的集合,你可能認為,你定義的這個List可以用來put任何T的子類,那麼我們看下面的程式碼:
import java.util.LinkedList; import java.util.List; public class test { public static void main(String[] args) { List<? extends Father> list = new LinkedList<>(); list.add(new Son()); } } class Human{ } class Father extends Human{ } class Son extends Father{ } class LeiFeng extends Father { }
list.add(new Son());這行會報錯:The method put(Son) is undefined for the type List<capture#1-of ? extends Father>
List<? extends Father> 表示 “具有任何從Son繼承型別的列表”,編譯器無法確定List所持有的型別,所以無法安全的向其中新增物件。可以新增null,因為null 可以表示任何型別。所以List 的add 方法不能新增任何有意義的元素,但是可以接受現有的子型別List 賦值。
你也許試圖這樣做:
List<? extends Father> list = new LinkedList<Son>(); list.add(new Son());
即使你指明瞭為Son型別,也不能用add方法新增一個Son物件。
list中為什麼不能加入Father類和Father類的子類呢,我們來分析下。
List<? extends Father>表示上限是Father,下面這樣的賦值都是合法的
List<? extends Father> list1 = new ArrayList<Father>(); List<? extends Father> list2 = new ArrayList<Son>(); List<? extends Father> list3 = new ArrayList<LeiFeng>();
如果List<? extends Father>支援add方法的話:
下面程式碼是編譯不通過的:
list1.add(new Father());//error list1.add(new Son());//error
原因是編譯器只知道容器內是Father或者它的派生類,但具體是什麼型別不知道。可能是Father?可能是Son?也可能是LeiFeng,XiaoMing?編譯器在看到後面用Father賦值以後,集合裡並沒有限定引數型別是“Father“。而是標上一個預留位置:CAP#1,來表示捕獲一個Father或Father的子類,具體是什麼類不知道,代號CAP#1。然後無論是想往裡插入Son或者LeiFeng或者Father編譯器都不知道能不能和這個CAP#1匹配,所以就都不允許。
所以萬用字元<?>和型別引數的區別就在於,對編譯器來說所有的T都代表同一種型別。比如下面這個泛型方法裡,三個T都指代同一個型別,要麼都是String,要麼都是Integer。
public <T> List<T> fill(T... t);
但萬用字元<?>沒有這種約束,List<?>單純的就表示:集合裡放了一個東西,是什麼我不知道。
所以這裡的錯誤就在這裡,List<? extends Father>裡什麼都放不進去。
List<? extends Father> list不能進行add,但是,這種形式還是很有用的,雖然不能使用add方法,但是可以在初始化的時候一個Season指定不同的型別。比如:
List<? extends Father> list1 = getFatherList();//getFatherList方法會返回一個Father的子類的list
另外,由於我們已經保證了List中儲存的是Father類或者他的某一個子類,所以,可以用get方法直接獲得值:
List<? extends Father> list1 = new ArrayList<>(); Father father = list1.get(0);//讀取出來的東西只能存放在Father或它的基礎類別裡。 Object object = list1.get(0);//讀取出來的東西只能存放在Father或它的基礎類別裡。 Human human = list1.get(0);//讀取出來的東西只能存放在Father或它的基礎類別裡。 Son son = (Son)list1.get(0);
下界用super進行宣告,表示引數化的型別可能是所指定的型別,或者是此型別的父類別型,直至Object。
//super只能新增Father和Father的子類,不能新增Father的父類別,讀取出來的東西只能存放在Object類裡 List<? super Father> list = new ArrayList<>(); list.add(new Father()); list.add(new Human());//compile error list.add(new Son()); Father person1 = list.get(0);//compile error Son son = list.get(0);//compile error Object object1 = list.get(0);
因為下界規定了元素的最小粒度的下限,實際上是放鬆了容器元素的型別控制。既然元素是Father的基礎類別,那往裡存粒度比Father小的都可以。出於對型別安全的考慮,我們可以加入Father物件或者其任何子類(如Son)物件,但由於編譯器並不知道List的內容究竟是Father的哪個超類,因此不允許加入特定的任何超類(如Human)。而當我們讀取的時候,編譯器在不知道是什麼型別的情況下只能返回Object物件,因為Object是任何Java類的最終祖先類。但這樣的話,元素的型別資訊就全部丟失了。
最後看一下什麼是PECS(Producer Extends Consumer Super)原則,已經很好理解了:
帶有super超型別限定的萬用字元可以向泛型物件中寫入,帶有extends子型別限定的萬用字元可以向泛型物件讀取。
到此這篇關於Java中 ? extends T 和 ? super T的理解的文章就介紹到這了,更多相關Java中 ? extends T 和 ? super T內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45