![](/img/trans.png)
[英]Generics compilation error with ternary operator in Java 8, but not in Java 7
[英]Compilation error with generics and ternary operator in JDK 7
編寫一些Java代碼時遇到編譯失敗,我將其提煉為以下測試用例:
import java.util.Collections;
import java.util.List;
public class TernaryFailure {
public static List<String> thisWorks() {
return Collections.emptyList();
}
public static List<String> thisFailsToCompile() {
return true ? Collections.emptyList() : Collections.emptyList();
}
}
上面的代碼無法使用javac
和JDK 1.7.0_45進行編譯:
$ javac TernaryFailure.java TernaryFailure.java:10: error: incompatible types return true ? Collections.emptyList() : Collections.emptyList(); ^ required: List<String> found: List<Object> 1 error
但是,它在JDK 1.8.0_05中編譯時沒有任何錯誤。
這是Java 7實現中的錯誤嗎? 或者是否對Java 8中的Java語言規范進行了增強以開始允許這樣做 - 如果是這樣,那么改變是什么?
JLS SE 8在( §15.2 )中說:
當某些表達式出現在某些上下文中時,它們被視為多重表達式。 以下表達形式可以是多義表達式:
帶括號的表達式(§15.8.5)
類實例創建表達式(第15.9節)
方法調用表達式(第15.12節)
方法參考表達式(§15.13)
條件表達式(§15.25)
Lambda表達式(§15.27)
因此,從規范的這一部分可以清楚地看出,條件表達式(三元運算符)可以被認為是多重表達式。 但並非所有條件表達式都可以被視為多重表達式,而只是根據(§15.25)引用條件表達式。 參考條件表達式可被視為多義表達式的條件在(§15.25.3)中闡明:
如果引用條件表達式出現在賦值上下文或調用上下文中(第5.2節.§5.3),則它是一個多表達式。 否則,它是一個獨立的表達式。
當poly引用條件表達式出現在具有目標類型T的特定類型的上下文中時,其第二和第三操作數表達式類似地出現在具有目標類型T的相同類型的上下文中。
多參考條件表達式的類型與其目標類型相同。
檢查在您的示例中,條件表達式出現在賦值上下文中,因為根據(§14.17) :
當帶有Expression的return語句出現在方法聲明中時,Expression必須可賦值(第5.2節)到方法的聲明返回類型,否則會發生編譯時錯誤。
那么在一天結束時,這一切意味着什么? 這意味着當條件表達式是多表達式時,目標類型被“下推”到每個操作數。 這樣,編譯器可以將條件的每個部分與目標相關聯。 在您的情況下,目標是List<String>
。 如果我們檢查emptyList()方法的定義,我們有:
@SuppressWarnings("unchecked")
public static final <T> List<T> emptyList() {
return (List<T>) EMPTY_LIST;
}
因此,使用目標List<String>
,編譯器可以推斷出T == String並且代碼被接受。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.