Java 8和广义目标类型推断

xde*_*000 20 java generics java-8

我安装了最后一个JDK 8 ea b114来测试新的语言功能.然而,链式调用中的推断似乎还没有奏效.

如果我写:

Iterator<String> it = new ArrayList<>().iterator();
Run Code Online (Sandbox Code Playgroud)

编译器给我一个错误.

然而,论证位置的推论效果很好.

也许不会插入链式调用中的推断?

Zho*_*gYu 17

正如@Holger所说,Java 8改进了上下文推理,这样就可以了

public static <T> Iterator<T> iter(Iterable<T> i)
{
    return i.iterator();
}

public static void main(String[] args)
{
    Iterator<String> it = iter( new ArrayList<>() );
                \____________________________/
}
Run Code Online (Sandbox Code Playgroud)

它在Java 7中不起作用 - 推断new ArrayList<>()不能依赖于上下文.


在问题中做你想做的事情对语言来说是一个巨大的变化.John Rose开始了类似的讨论,请参阅 http://mail.openjdk.java.net/pipermail/lambda-dev/2013-July/010531.html


过多的推理和过多的上下文依赖可能是一件坏事.并不是说编译器无法处理复杂性 - 它可以.这是关于人类程序员是否能够处理它.我感觉Java 8已经处于危险的水平,人类难以解析代码.

  • 好吧,我看到有一个类似于邮件列表中的示例的案例,其中类型推断可能会影响选择哪个重载方法.但是我真的希望他们为没有重载方法的99%的情况实现类型推断(比如在`iterator()`示例中),并且仅为重载方法禁止它,而不是因为这些而拒绝所有情况1角落情况的百分比(或更少). (5认同)
  • "我感觉Java8已经处于一个危险的水平,人类很难解析这些代码." IDE的功能,例如on-signature-on-hover(显示推断的泛型类型信息),可以更容易地解析这些东西. (3认同)

Ben*_*ulz 13

最新规范(公共评论)可在jcp.org上获得.D部分有一段讨论这一点.

方法调用,字段访问等(exp.foo())中的接收器不是聚合表达式,因为目标类型是未知的 - 不可能枚举具有特定成员的每个类型(在这种情况下为foo) ).允许推理"链"有一些兴趣:在a().b()中,将类型信息从b的调用传递给a的调用.这为推理算法的复杂性增加了另一个维度,因为部分信息必须在两个方向上传递; 它只适用于a()的返回类型的擦除对于所有实例化(例如List)是固定的.此特征不适合多聚表达式模型,因为无法轻松导出目标类型.

  • @Holger我只能说这是一个非常难的问题.从事规范和实施的人员都很聪明.他们也编写Java代码,我相信他们希望这样做尽可能愉快.所以他们让它不如想象的那么愉快,然后我怀疑是因为缺乏尝试. (4认同)
  • 听起来他们想再次强迫我们为我们的代码添加过时的帮助方法只是为了让编译器开心... :-( (3认同)
  • @Holger这两个人处于不同的难度级别.构造函数在推理方面有点像静态方法; 它更像是java5中的疏忽而不是对构造函数进行推理.链式方法调用是一种完全不同的动物. (2认同)
  • 一些相关的讨论由john rose开始 - http://mail.openjdk.java.net/pipermail/lambda-dev/2013-July/010531.html (2认同)