不爲人知的Java8特性:泛化目標類型推斷

本文由 ImportNew - 彭秦進 翻譯自 javacodegeeks。如需轉載本文,請先參見文章末尾處的轉載要求。

ImportNew注:若是你也對Java技術翻譯分享感興趣,歡迎加入咱們的 Java開發 小組。參與方式請查看小組簡介。 html

在瀏覽Java8的特性列表的時候,目標類型推斷這個特別有趣的、不爲人知的特性一會兒吸引了我。Java語言的設計者經過它讓咱們減輕了一些使用泛型時(Java5-7)的痛苦。讓咱們來看看過去泛型使用的示例: java

class List<E> {
  static <Z> List<Z> nil() {..}
  static <Z> List<Z> cons(Z head, List<Z> tail) {..}
  E head() {..}
}
在上述例子,在 JEP:101中聲稱能夠用下面的方法更好地表示:
// 建議寫法:
List.cons(42, List.nil());
String s = List.nil().head();
 
// 不推薦的寫法:
List.cons(42, List.<Integer>nil());
String s = List.<String>nil().head()
做爲一個 熟練的API設計師,在Java路線圖中看到示例中的進步着實使人激動。這些使人興奮的變化究竟包含了什麼?讓我來更加詳細地說明:
// 經過賦值語句推斷泛型的類型
List<String> l = List.nil();
 
// 更好的辦法是讓編譯器從函數的參數類型中直接推斷
List.cons(42, List.nil());
 
// 或者從「鏈式調用」中推斷
String s = List.nil().head();
所以在上面的鏈式方法調用中,會延遲到整個賦值表達式完成時才進行類型推斷。經過賦值語句左邊,編譯器會爲head()調用推斷;爲String。而後,再次推斷nil()調用的爲String。 在我看來這真的很神奇。 對nil()方法的AST計算會延遲到「關聯」子節點計算時才最後完成。這是一個很棒的主意,不是嗎?

是的,確實很棒! api

你可能也會這麼認爲。由於一組流暢的API,像 jooq 或 Stream API在設計時會考慮到這種調用的流暢性,在鏈式調用的最後才進行類型推斷。爲此,我下載了最新的JDK 8評估版本測試下面的程序: less

public class InferenceTest {
    public static void main(String[] args) {
        List<String> ls = List.nil();
        List.cons(42, List.nil());
        String s = List.nil().head();
    }
}
如下是獲得的編譯結果:
C:\Users\Lukas\java8>javac InferenceTest.java
InferenceTest.java:5: error: incompatible types:
    Object cannot be converted to String
        String s = List.nil().head();
                                  ^
1 error
從結果中能夠看到,基於該方法參數的類型推斷已經實現了(所以編譯經過了),可是鏈式方法調用中的類型推斷尚未實現。我在網上搜索到了一個解釋,從 Stack OverFlow 問題連接到 lambda-dev開發者郵件列表中。

看來,Java類型系統已經變得至關複雜。因爲太過複雜,要實現這種瘋狂的類型推斷變得不太現實。可是,天天編寫Java 8代碼的時候,即便略有改善也有重大的價值。 函數

最後,但願在Java 9中會有val和 var 這樣的關鍵字,與其餘語言同樣。 測試


原文連接: javacodegeeks 翻譯: ImportNew.com - 彭秦進
譯文連接: http://www.importnew.com/8301.html
[ 轉載請保留原文出處、譯者和譯文連接。]
相關文章
相關標籤/搜索