Java8 Lambdas和Exceptions

rom*_*oll 66 java lambda java-8

我想知道是否有人可以向我解释以下奇怪之处.我正在使用Java 8更新11.

鉴于这种方法

private <F,T> T runFun(Function<Optional<F>, T> fun, Optional<F> opt) {
   return fun.apply(opt) ;
}
Run Code Online (Sandbox Code Playgroud)

如果我首先构造一个函数Object,并将其传递给上面的方法,那么事情就会编译.

private void doesCompile() {
    Function<Optional<String>, String> fun = o -> o.orElseThrow(() -> new RuntimeException("nah"));
    runFun(fun, Optional.of("foo"));

}
Run Code Online (Sandbox Code Playgroud)

但是,如果我将函数内联为lambda,编译器会说

未报告的例外X; 必须被抓住或宣布被抛出

private void doesNotCompile () {
    runFun(o -> o.orElseThrow(() -> new RuntimeException("nah")), Optional.of("foo"));
}
Run Code Online (Sandbox Code Playgroud)

更新:原来错误消息由maven缩写.如果直接用javac编译,则错误是:

error: unreported exception X; must be caught or declared to be thrown
            runFun(o -> o.orElseThrow(() -> new RuntimeException("nah")), Optional.of("foo"));
                                     ^
  where X,T are type-variables:
    X extends Throwable declared in method <X>orElseThrow(Supplier<? extends X>)
    T extends Object declared in class Optional
Run Code Online (Sandbox Code Playgroud)

另请参见此处的可运行测试代码.

kei*_*sar 92

这就是我解决问题的方法:

而不是写作

optional.map(this::mappingFunction).orElseThrow(() -> new BadRequestException("bla bla"));
Run Code Online (Sandbox Code Playgroud)

我写:

optional.map(this::mappingFunction).<BadRequestException>orElseThrow(() -> new BadRequestException("bla bla"));
Run Code Online (Sandbox Code Playgroud)

添加显式<BadRequestException>帮助这些lambda边缘情况(这是非常烦人的......)

更新:如果你不能更新到最新的JDK版本,你应该...

  • 我使用的是最新版本的Java,但仍然出现错误。。&lt;RuntimeException&gt; getOrElseThrow(throwable帮助了我。谢谢。 (2认同)
  • 我在1.8.0_144,仍然需要使用你的解决方案.它有所帮助 (2认同)
  • 1.8.0_181 也需要显式转换。 (2认同)

Sea*_*der 41

这看起来像是JDK-8054569的错误,它不会影响Eclipse.

我可以通过将Supplier替换为Supplier并缩小方法来缩小范围orElseThrow:

abstract <T> void f(Supplier<T> s);

abstract <T, X extends Throwable> T g(Supplier<? extends X> x) throws X;

void bug() {
    f(() -> g(() -> new RuntimeException("foo")));
}
Run Code Online (Sandbox Code Playgroud)

然后进一步删除供应商和lambdas:

abstract <T> void f(T t);

abstract <T, X extends Throwable> T g(X x) throws X;

void bug() {
    f(g(new RuntimeException("foo")));
}
Run Code Online (Sandbox Code Playgroud)

这实际上是一个比bug报告中更清晰的例子.如果编译为Java 8,则显示相同的错误,但可以正常工作-source 1.7.

我想有关将泛型方法返回类型传递给泛型方法参数会导致异常的类型推断失败,因此它假定类型为Throwable并且抱怨未处理此已检查的异常类型.如果声明bug() throws Throwable或更改绑定X extends RuntimeException(因此未选中),则错误消失.

  • 从1.8.0_45更新到1.8.0_92,它解决了我的问题.谢谢 (11认同)