此代码在 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
最佳答案
为什么?
因为泛型类型的类型推断还没有扩展到链式调用。
来自 java tutorial on generics type inference :
The notion of what is a target type has been expanded to include method arguments.
这就是为什么这段代码:
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 部分):
There has been some interest in allowing inference to "chain": in a().b(), passing type information from the invocation of b to the invocation of a. This adds another dimension to the complexity of the inference algorithm, as partial information has to pass in both directions; it only works when the erasure of the return type of a() is fixed for all instantiations (e.g. List). This feature would not fit very well into the poly expression model, since the target type cannot be easily derived; but perhaps with additional enhancements it could be added in the future.
所以也许在 Java 9 中。
关于java - 泛型类型推断不适用于方法链接?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24794924/