簡體   English   中英

JDK 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM