Java8 Lambdas和Exceptions [英] Java8 Lambdas and Exceptions

查看:113
本文介绍了Java8 Lambdas和Exceptions的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I wonder if someone could explain the following weirdness to me. I'm using Java 8 update 11.

给定此方法

private <F,T> T runFun(Function<Optional<F>, T> fun, Optional<F> opt) {
   return fun.apply(opt) ;
}

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

If I first construct a function Object, and pass that in to the method above, things compile.

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

}

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

But, if I inline the function as a lambda, the compiler says


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

unreported exception X; must be caught or declared to be thrown



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






更新
原来错误信息由maven缩写。如果直接使用javac编译,则错误为:


Update: Turns out the error message was abbreviated by maven. If compiled directly with javac, the error is:

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

另见这里为可运行的测试代码。

Also see here for runnable test code.

推荐答案

这看起来像是一个bug的案例 JDK-8054569 ,它不会影响Eclipse。

This looks like a case of bug JDK-8054569, which doesn't affect Eclipse.

我能够通过用Supplier替换Function并缩小 orElseThrow 方法来缩小范围:

I was able to narrow it down by replacing Function with Supplier and extracting the orElseThrow method:

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")));
}

然后完全删除供应商和lambdas:

and then further by removing the suppliers and lambdas altogether:

abstract <T> void f(T t);

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

void bug() {
    f(g(new RuntimeException("foo")));
}

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

which is actually a cleaner example than the one in the bug report. This shows the same error if compiled as Java 8, but works fine with -source 1.7.

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

I guess something about passing a generic method return type to a generic method parameter causes the type inference for the exception to fail, so it assumes the type is Throwable and complains that this checked exception type isn't handled. The error disappears if you declare bug() throws Throwable or change the bound to X extends RuntimeException (so it's unchecked).

这篇关于Java8 Lambdas和Exceptions的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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