第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

為什么 List<?super Number > 可以包含 String

為什么 List<?super Number > 可以包含 String

達令說 2021-12-22 15:15:49
我試著理解泛型中的通配符,我有一個問題 List<? super Number >可以引用任何對象列表并將任何對象添加到這個列表中,但我不能添加到它對象不擴展數(shù)字(字符串)但為什么我可以這樣做在此代碼中,在運行時沒有任何編譯錯誤或異常(指列表包含 String 對象)編輯:我想了解泛型提供編譯時安全,而這在我的示例中沒有實現(xiàn)List <? super Object> objectList = new ArrayList<>();objectList.add("str1");List<? super Number> numberList = objectList;numberList.add(1);objectList.add("str2");for (int i = 0; i < objectList.size(); i++) {    System.out.println(objectList.get(i) + "");} 
查看完整描述

3 回答

?
三國紛爭

TA貢獻1804條經(jīng)驗 獲得超7個贊

您有兩種不同類型的多態(tài)性在這里以一種令人困惑的方式相互作用。


理解這一點的關(guān)鍵在于,除了參數(shù)多態(tài)性(即泛型)之外,還有子類型多態(tài)性,即經(jīng)典的面向?qū)ο蟮摹癷s-a”關(guān)系。


在 Java 中,所有對象都是Object. 所以一個可以包含Object值的容器可以包含任何值。


如果我們像剛才<Object>那樣重寫所有通用邊界,代碼的工作方式相同,顯然如此:


List<Object> objectList = new ArrayList<>();

objectList.add("str1");


List<Object> numberList = objectList;

numberList.add(1);


objectList.add("str2");

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

    System.out.println(objectList.get(i) + "");

}

具體來說,objectList.get(i) + ""被評估為調(diào)用 的東西objectList.get(i).toString(),并且由于toString()是 的方法Object,無論 中的對象類型如何,它都將起作用objectList。


這是行不通的:


Number number = numberList.get(i);  // error!

這是因為,盡管名稱具有誤導(dǎo)性,但numberList不能保證僅包含Number對象,并且實際上可能根本不包含任何Number對象!


讓我們來看看為什么會這樣。


首先我們創(chuàng)建一個對象列表:


List<? super Object> objectList = new ArrayList<>();

這種類型是什么意思?類型的List<? super Object>意思是“某種類型的對象列表,我不能告訴你是什么類型,但我知道它是什么類型,Object或者是”的超類型Object。我們已經(jīng)知道這Object是子類型層次結(jié)構(gòu)的根,所以這實際上與 相同List<Object>:即這個對象只能包含Object對象。


但是……這不太對。列表只能包含Object對象,但Object對象可以是任何東西!runtype 中的實際對象可以是任何類型的子類型Object(因此,除了原始類型之外的任何其他類型),但是將它們放入此列表中,您將無法再分辨它們是哪種類型的對象——他們可以是任何東西。不過,這對于該程序的其余部分所做的事情來說是可以的,因為它需要能夠做的就是調(diào)用toString()對象,并且它可以做到這一點,因為它們都擴展了Object.


現(xiàn)在讓我們看看另一個變量聲明:


List<? super Number> numberList = objectList;

再次,類型List<? super Number>是什么意思?至關(guān)重要的是,它的意思是“某種類型的對象列表,我不能告訴你它是什么類型,但我知道無論它是什么類型,它都是“的一種Number或某種超類型Number”。好吧,在左邊我們有一個“Number或某個超類型Number”的列表,在右邊我們有一個列表Object——顯然Object是一個的超類型,Number所以這個列表是一個列表Object。一切類型檢查(并且,與我最初的評論相反,沒有任何警告)。


所以問題就變成了:為什么 a 可以List<? super Number>包含 a String?因為 aList<? super Number>可以只是 a List<Object>,而 aList<Object>可以包含 aString因為Stringis-a Object。


查看完整回答
反對 回復(fù) 2021-12-22
?
元芳怎么了

TA貢獻1798條經(jīng)驗 獲得超7個贊

類型的List<? super Number>引用可以引用List<Object>List<Number>。通過此引用進行的任何操作都需要使用這些類型中的任何一種。您無法通過List<? super Number>引用添加字符串,因為該操作僅適用于一種可能的對象類型,但您可以通過List<? super Object>引用。

AList<? super Object>只能引用 a List<Object>。AList<? super Number>可以指代 aList<Number>或 a List<Object>。這是一種更通用的類型,這就是允許賦值的原因。



查看完整回答
反對 回復(fù) 2021-12-22
?
互換的青春

TA貢獻1797條經(jīng)驗 獲得超6個贊

當(dāng)編譯器看到:


List<? super Number> numberList = objectList;

它首先捕獲通配符。泛型類型變?yōu)?Y = X >Number(意味著Number的具體超類型)。所以我們有:


List<Y> numberList = objectList //with type of List<Object>;

然后編譯器確定Y可以替換為Object。因此,類型是相同的,numberList并且允許指向與 相同的對象objectList。


然后將生成的字節(jié)碼傳遞給運行時系統(tǒng)執(zhí)行。就運行時系統(tǒng)而言,java.util.ArrayList由于類型擦除,兩個列表都具有類型。因此,當(dāng)您將字符串或其他對象放入此容器時,不會引發(fā)運行時異常。


但我也覺得有些地方不太對勁。重新表述你的問題:


編譯器可以做什么來防止這種情況?


請注意,編譯器不得在賦值期間抱怨,因為:


安全實例化原則:實例化具有滿足參數(shù)聲明約束的類型的參數(shù)類不應(yīng)導(dǎo)致錯誤。


我認為這個原則也適用于作業(yè)。賦值不會破壞任何語言規(guī)則,因此編譯器不得引發(fā)錯誤。


因此,唯一可以將程序員從災(zāi)難中拯救出來的地方就是在add操作期間。但是編譯器在那里能做什么呢?如果它因為賦值而不允許add操作objectList,那將破壞其他語言規(guī)則。如果它增強add以支持向 中添加對象numberList,那也會違反其他一些語言規(guī)則。


我想不出任何簡單易行的解決方案不會破壞很多東西來修復(fù)甚至可能不是問題的東西,而程序員當(dāng)然處于決定地位的好位置。


類型檢查器旨在幫助程序員不要取代她。另一個不完美的例子:


public static void main(String[] args) {

    Object m = args;

    String[] m2 = m; //complains, despite m2 definitely being an String[]

}

PS:我在SO上找到了上面的例子,但不幸的是,我失去了鏈接!


查看完整回答
反對 回復(fù) 2021-12-22
  • 3 回答
  • 0 關(guān)注
  • 240 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動學(xué)習(xí)伙伴

公眾號

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號