2014-07-17 141 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.也许