通用类型推断不适用于方法链? [英] Generic type inference not working with method chaining?

查看:35
本文介绍了通用类型推断不适用于方法链?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此代码可在 Java 8 中编译,但在 Java 7 中无法编译:

This code compiles in Java 8 but fails to compile in 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.empty() 返回的 Map 的具体类型:

It doesn't infer the concrete type of the Map being returned from 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.empty());,它会编译.在 Java 8 中,它无需求助于此.

It compiles if you change the f call to f(Map.<Integer,String>empty());. In Java 8, it works without having to resort to this.

但是如果您将 f 调用更改为 f(Map.empty().put(1,"A").put(2,"B"));,在 Java 7 和 8 上都无法再次编译.为什么?

But if you change the f call to f(Map.empty().put(1,"A").put(2,"B"));, it fails to compile once again, on both Java 7 and 8. Why?

$ $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

推荐答案

为什么?

因为泛型类型的类型推断没有扩展到链式调用.

Because the type inference of generics types has not been expanded to chained invocation.

来自关于泛型类型推断的java教程:

什么是目标类型的概念已经扩展到包括方法参数.

The notion of what is a target type has been expanded to include method arguments.

这就是为什么这个代码:

That is why this code:

f(Map.empty());

编译.

但是这段代码没有,因为这是一个链式调用:

But this code doesn't because this is a chained invocation:

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

<小时>

您还可以在 JSR-000335 Lambda 表达式中找到一小段JavaTM 编程语言最终评估版(特别是 D 部分):


You can also find a small paragraph in the JSR-000335 Lambda Expressions for the JavaTM Programming Language Final Release for Evaluation (specifically part D):

允许推断链"有一些兴趣:在 a().b() 中,将类型信息从 b 的调用传递到 a 的调用.这为推理算法的复杂性增加了另一个维度,因为部分信息必须双向传递;它仅在 a() 的返回类型的擦除对于所有实例(例如列表)都是固定的时才有效.这个特性不太适合多表达式模型,因为目标类型不容易导出;但也许在未来可以添加其他增强功能.

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 中.

So maybe in Java 9.

这篇关于通用类型推断不适用于方法链?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆