[英]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成功编译,而javac
仍然失败。 当我将<RuntimeException>
作为类型参数添加到第二个参数时, javac
,Eclipse失败而javac
成功。
问题:再次,编译器是否拒绝该调用,为什么?
在我看来,这两种变体都应该使用类型参数来编译,而没有其他提示。 如果是这样,我将为javac
填写一份错误报告(关于“未报告的异常”),对于Eclipse编译器填写一份错误报告(关于“类型不匹配”)。 但是首先,我想确保规范与我保持一致。
使用的版本:
javac
:1.8.0_66 编辑:
我在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。 编译器应该能够推断X
为RuntimeException
。 至于为什么Eclipse仍然不能编译它,再次,我在他们的Bugzilla中找不到任何东西,所以请随时报告!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.