2014-04-30 57 views
7

我遇到了一個編譯失敗,而寫一些Java代碼,這是我蒸餾至下面的試驗情況下編譯錯誤:泛型和三元運算在JDK 7

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語言規範進行了改進以開始允許這一點 - 如果是的話,那麼改變是什麼?

+0

http://stackoverflow.com/questions/21258160/why-is-javas-type-in​​ference-so-weak – assylias

+0

三元運算符與普通回報結合會出現問題,這是衆所周知的。顯式指定類型參數。 – qqilihq

回答

4

的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。 )。否則,這是一個獨立的表達。

凡聚參考條件表達式出現在一個特定種類的靶與類型T的範圍內,它的第二和第三操作數的表達式類似地出現在相同的種與目標類型T.

的類型的上下文多參考條件表達式與其目標類型相同。

檢查你的榜樣條件表達式,因爲根據(§14.17)出現在分配方面:

當與表達一個return語句出現在方法聲明,表達必須是分配(§ 5.2)到方法的聲明返回類型,或發生編譯時錯誤。

那麼在一天結束時,這一切意味着什麼?這意味着當條件表達式是多表達式時,目標類型被「下推」到每個操作數。通過這種方式,編譯器可以將條件的每個部分都歸於目標。在你的情況下,目標是List<String>。如果我們檢查的emptyList()方法的定義,我們有:

@SuppressWarnings("unchecked") 
public static final <T> List<T> emptyList() { 
    return (List<T>) EMPTY_LIST; 
} 

因此與目標List<String>,編譯器可以推斷是t ==字符串和代碼被接受。