亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

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

開發中遇到的一個java泛型的問題

開發中遇到的一個java泛型的問題

幕布斯6054654 2019-03-15 14:15:13
   private static List<String> getList(String content){//        return content==null ? Collections.emptyList():new ArrayList<String>();//error: cannot convert from List<capture#1-of ? extends Object> to List<String>//        return content==null ? Collections.<String>emptyList():new ArrayList<String>();//ok          return Collections.emptyList();//ok    }為什么第一種方法要報錯,但最后一種卻可以?
查看完整描述

5 回答

?
呼啦一陣風

TA貢獻1802條經驗 獲得超6個贊

出錯原因是你使用了一個引用條件表達式(reference conditional expression)來給變量賦值,并且你的java se版本不是8.0

由于條件表達式不在變量賦值或者調用的上下文中,屬于standalone reference conditional expression,這種表達式的類型推斷有三條的規則:

  1. 當第二、第三表達式類型相同時,該類型作為條件表達式的類型

  2. 當第二、第三表達式類型其中之一是 null type,另一個是引用類型,引用類型作為條件表達式的類型

  3. 當第二、第三表達式類型分別為s1、 s2,t1、t2分別為s1、s2經過自動裝箱轉換后的類型,則 應用過capture conversion 的lub(t1, t2)為表達式類型

由于你的條件表達式第二個和第三個表達式類型不一樣,分別是 List<T> 和 List<String> ,由于沒有給emptyList()指定類型,所以這里T是Object。適用第三條規則,最終的類型是 lub(List<Object>, List<String>) ,lub是 least upper bound 的縮寫,在這里指最小公共上界,結果是 List<? extends Object>。
至于 capture conversion,主要是為了從含有通配符的泛型中推斷公共上界,我不清楚在這里對類型有沒有貢獻,猜測沒有。

所以到最后賦值的時候會報錯,因為賦值類型和表達式類型不匹配。


查看完整回答
反對 回復 2019-04-16
?
縹緲止盈

TA貢獻2041條經驗 獲得超4個贊

因為使用了 expression?expression:expression這樣的語句,所以有問題。
如果你用if語句就沒問題了。

Collections.emptyList()的泛型取決于它要賦予的變量(或返回值等)的類型,所以最后一個是對的。
但是,【expression?expression:expression】這個語句的結果會有一個默認的Object來接收,
然后在轉換成要賦予的變量的類型,那么導致Collections.emptyList()給Object類型賦值,無法判斷泛型,所以報錯。
通過實驗可以驗證,如下:
Object a = content==null ? "2":1;


查看完整回答
反對 回復 2019-04-16
?
一只甜甜圈

TA貢獻1836條經驗 獲得超5個贊

首先你方法的返回值是List<String>,所以你需要return這個類型的對象。
其實答案就是Collections.emptyList()其實是Object類型的List,而你的返回值要求都是String類型的List,所以肯定報錯呀。

查看完整回答
反對 回復 2019-04-16
?
慕妹3146593

TA貢獻1820條經驗 獲得超9個贊

經測試,如下這行代碼在jdk8下是不報錯的(jdk7應該也是可以的,但暫時沒有測試)。而之前這里的報錯是在jdk6環境下。


return content==null ? Collections.emptyList():new ArrayList<String>();//error: cannot convert from List<capture#1-of ? extends Object> to List<String>

再測試,如下代碼在jdk6下也是OK的。


return content==null ? Collections.emptyList():new ArrayList();

也就是說三目運算符的兩個返回類型都是原始List類型就可以。

對比上面的報錯,可以初步判定編譯出錯原因是,因為編譯時就可以通過new ArrayList<String>可以推斷出方法返回類型是List<String>(String泛型類型已經被記錄),而Collections.emptyList()又是原始List類型.如果運行時返回后者原始List,就可能出現convert from List<capture#1-of ? extends Object> to List<String>。而現在,在編譯時就直接報錯來避免這種運行時的強轉錯誤。

因此,返回兩個原始類型可以編譯通過這個也能解釋了,因為編譯時并不能確定下他們的確切返回類型(根據類型擦除原理,實際方法返回類型是List<Object>),所以兩種返回convert from List<capture#1-of ? extends Object> to List<Object>是OK的。


以上只是個人測試下半猜測的結論,并沒有Oracle相關文檔支持,如果有錯誤,請大家指正。


查看完整回答
反對 回復 2019-04-16
?
哈士奇WWW

TA貢獻1799條經驗 獲得超6個贊

沒什么好討論的,和JAVA版本有關,了解下 類型推斷 這個東西就行了。


查看完整回答
反對 回復 2019-04-16
  • 5 回答
  • 0 關注
  • 783 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號