繁体   English   中英

泛型和lambdas-Javac和Eclipse编译器中的不同行为

[英]Generics and lambdas - different behavior in javac and Eclipse compiler

注意:我发现了多个问题,指出了javac和Eclipse编译器之间的区别,但是据我所知,所有这些都讨论了其他问题。

假设我们有这种方法:

public static <T, U> void foo(Supplier<T> a, Function<T, U> b, Consumer<U> c)
{
    c.accept(b.apply(a.get()));
}

在编译对该方法的调用时,我发现javac与Eclipse Java编译器之间的行为不同,但我不确定两者中哪一个正确。


此方法的简单用法可以是:

// variant 1
foo(
    () -> Optional.of("foo"),
    value -> value.get(),
    value -> System.out.println(value));

编译器应该能够使用第一个参数将T绑定到Optional<String> ,并使用第二个参数将U绑定到String 因此,此通话应该有效(我认为)。

使用javac很好地javac但是不能使用Eclipse编译:

类型不匹配:无法从void转换为<unknown>

在第一个参数( () -> Optional.<String> of("foo") ))中添加类型参数也使其可以在Eclipse中进行编译。

问:从规范的角度来看,Eclipse拒绝此调用是否正确(为什么(不))?


现在假设如果Optional为空,我们想抛出一个自定义(运行时)异常:

// variant 2
foo(
    () -> Optional.of("foo"),
    value -> value.orElseThrow(() -> new RuntimeException()),
    value -> System.out.println(value));

javac和Eclipse编译器均拒绝此操作,但是具有不同的错误消息:

  • javac :“未报告的异常X;必须被捕获或声明为抛出”
  • Eclipse编译器:“类型不匹配:无法从void转换为<unknown>”

当如上所述将类型参数添加到第一个参数时,Eclipse成功编译,而javac仍然失败。 当我将<RuntimeException>作为类型参数添加到第二个参数时, javac ,Eclipse失败而javac成功。

问题:再次,编译器是否拒绝该调用,为什么?


在我看来,这两种变体都应该使用类型参数来编译,而没有其他提示。 如果是这样,我将为javac填写一份错误报告(关于“未报告的异常”),对于Eclipse编译器填写一份错误报告(关于“类型不匹配”)。 但是首先,我想确保规范与我保持一致。

使用的版本:

  • javac :1.8.0_66
  • Eclipse JDT:3.11.1.v20151118-1100

编辑:

我在Eclipse中填充了错误482781

javac的问题已报告为JDK-8056983 ,请参见Tunakis的答案

是的,您在各个方面都是正确的。 老实说,我将无法链接到JLS的特定行上:类型推断是一整章

免责声明:我使用Eclipse Mars 4.5.1和JDK 1.8.0_60进行了测试。


变体1应该可以编译,并且Eclipse在这里有一个错误。 我在他们的Bugzilla中找不到与此相关的任何内容,因此您可以继续进行归档。 如果将示例简化为以下内容,则可以确保可以编译它:

public static <T> void foo(Supplier<T> a) {
    a.get();
}

foo(() -> Optional.of("foo"));

Eclipse和javac都可以很好地javac 添加参数不会(不应)更改编译期间为T推断的类型。


JDK-8056983中所述,变体2不能为javac ,这确实是一个bug。 编译器应该能够推断XRuntimeException 至于为什么Eclipse仍然不能编译它,再次,我在他们的Bugzilla中找不到任何东西,所以请随时报告!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM