java - 泛型类型推断不适用于方法链接?

标签 java generics java-7 java-8 type-inference

此代码在 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/

相关文章:

java - 检测 TCP 连接重置的方法

C# typedef 泛型

java - 尝试限制 Number 类的上限而不为整个类实现 Comparable

java - Java 7.x 中的验证树不起作用(在 Java 6.x 中很好)

java - 无法理解如何在 java 中定义列表列表

java - 围绕 Sytem.in 和 System.out 进行 JUnit 测试

java - 如何使用 Java Trident 库在 CardLayout 中制作面板动画?

java - 通过 java jmx 功能调用方法,其中参数是 ArrayList

delphi - 如何检测 TDictionary 大小的增加

jakarta-ee - jdk1.7/jre/lib/rt.jar的访问限制