该代码在Java 8中编译,但在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());
}
}
它不能推断出Map
从中返回的具体类型Map.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
为什么呢
因为泛型类型的类型推断尚未扩展为链式调用。
什么是目标类型的概念已扩展为包括方法参数。
这就是为什么此代码:
f(Map.empty());
编译。
但是,此代码不是因为这是链接调用:
f(Map.empty().put(1,"A").put(2,"B"));
您还可以在JavaTM编程语言最终评估版的JSR-000335 Lambda表达式中找到一小段(特别是D部分):
允许推理到“链”已经引起了一些兴趣:在a()。b()中,将类型信息从b的调用传递到a的调用。由于部分信息必须在两个方向上传递,这为推理算法的复杂性增加了另一个维度。它仅在所有实例化(例如List)的a()返回类型的擦除固定时有效。由于无法轻松导出目标类型,因此该功能不太适合多表达式模型。但也许有其他增强功能可以在将来添加。
所以也许在Java 9中。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句