2014-07-17 104 views
24

這種失敗在Java 7中編譯:泛型類型推斷不適用於方法鏈接?

class Map<K,V> { 
    static <K,V> Map<K,V> empty() {return null;} 
    Map<K,V> put(K k, V v) {return null;} 
    V get(K k) {return null;} 
} 

class A { 
    static void f(Map<Integer,String> m){} 
    public static void main(String[] args) { 
     f(Map.empty()); 
    } 
} 

它並不推斷MapMap.empty()返回的具體類型:

$ javac7 A.java 
A.java:10: error: method f in class A cannot be applied to given types; 
     f(Map.empty()); 
     ^
    required: Map<Integer,String> 
    found: Map<Object,Object> 
    reason: actual argument Map<Object,Object> cannot be converted to Map<Integer,String> by method invocation conversion 
1 error 

,如果你改變了f調用f(Map.<Integer,String>empty());編譯。在Java 8中,它不需要訴諸這些。

但是,如果您將f調用更改爲f(Map.empty().put(1,"A").put(2,"B"));,則無法在Java 7和8上再次編譯。爲什麼?

$ $javac7 A.java 
A.java:10: error: method f in class A cannot be applied to given types; 
     f(Map.empty().put(1,"A").put(2,"B")); 
     ^
    required: Map<Integer,String> 
    found: Map<Object,Object> 
    reason: actual argument Map<Object,Object> cannot be converted to Map<Integer,String> by method invocation conversion 
1 error 

$ $javac8 A.java 
A.java:10: error: incompatible types: Map<Object,Object> cannot be converted to Map<Integer,String> 
     f(Map.empty().put(1,"A").put(2,"B")); 
            ^
Note: Some messages have been simplified; recompile with -Xdiags:verbose to get full output 
1 error 

$ $javac8 -Xdiags:verbose A.java 
A.java:10: error: method f in class A cannot be applied to given types; 
     f(Map.empty().put(1,"A").put(2,"B")); 
     ^
    required: Map<Integer,String> 
    found: Map<Object,Object> 
    reason: argument mismatch; Map<Object,Object> cannot be converted to Map<Integer,String> 
1 error 
+0

只是使它'靜態地圖空(){返回NULL;}',它不喜歡你將使用泛型反正任何修飾。 –

回答

24

爲什麼?

因爲泛型類型的類型推斷尚未擴展爲鏈式調用。

java tutorial on generics type inference

的是什麼目標類型已經擴大到包括方法參數的概念。

這就是爲什麼這個代碼:

f(Map.empty()); 

編譯。

但此代碼不會,因爲這是一個鏈式調用:

f(Map.empty().put(1,"A").put(2,"B")); 

您還可以找到在JSR-000335 Lambda Expressions for the JavaTM Programming Language Final Release for Evaluation(特別是部分d)一個小段落:

有在允許推斷「鏈」方面有一些興趣:在()。b()中,將調用b的類型信息傳遞給a的調用。這給推理算法的複雜性增加了另一個維度,因爲部分信息必須在兩個方向上傳遞;它只適用於刪除a()的返回類型對所有實例(例如List)都是固定的。由於目標類型不易導出,因此此功能不適合多表達式模型。但是可能會增加額外的功能,以後可能會添加。

所以在Java中9.也許