5 回答

TA貢獻1802條經驗 獲得超6個贊
出錯原因是你使用了一個引用條件表達式(reference conditional expression)來給變量賦值,并且你的java se版本不是8.0
由于條件表達式不在變量賦值或者調用的上下文中,屬于standalone reference conditional expression,這種表達式的類型推斷有三條的規則:
當第二、第三表達式類型相同時,該類型作為條件表達式的類型
當第二、第三表達式類型其中之一是 null type,另一個是引用類型,引用類型作為條件表達式的類型
當第二、第三表達式類型分別為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,主要是為了從含有通配符的泛型中推斷公共上界,我不清楚在這里對類型有沒有貢獻,猜測沒有。
所以到最后賦值的時候會報錯,因為賦值類型和表達式類型不匹配。

TA貢獻2041條經驗 獲得超4個贊
因為使用了 expression?expression:expression這樣的語句,所以有問題。
如果你用if語句就沒問題了。
Collections.emptyList()的泛型取決于它要賦予的變量(或返回值等)的類型,所以最后一個是對的。
但是,【expression?expression:expression】這個語句的結果會有一個默認的Object來接收,
然后在轉換成要賦予的變量的類型,那么導致Collections.emptyList()給Object類型賦值,無法判斷泛型,所以報錯。
通過實驗可以驗證,如下:
Object a = content==null ? "2":1;

TA貢獻1836條經驗 獲得超5個贊
首先你方法的返回值是List<String>,所以你需要return這個類型的對象。
其實答案就是Collections.emptyList()其實是Object類型的List,而你的返回值要求都是String類型的List,所以肯定報錯呀。

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相關文檔支持,如果有錯誤,請大家指正。
添加回答
舉報