Java8 Lambda 和异常
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/25523375/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java8 Lambdas and Exceptions
提问by rompetroll
I wonder if someone could explain the following weirdness to me. I'm using Java 8 update 11.
我想知道是否有人可以向我解释以下奇怪之处。我正在使用 Java 8 更新 11。
Given this method
鉴于这种方法
private <F,T> T runFun(Function<Optional<F>, T> fun, Optional<F> opt) {
return fun.apply(opt) ;
}
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"));
}
But, if I inline the function as a lambda, the compiler says
但是,如果我将函数内联为 lambda,编译器会说
unreported exception X; must be caught or declared to be thrown
未报告的异常 X;必须被捕获或声明被抛出
private void doesNotCompile () {
runFun(o -> o.orElseThrow(() -> new RuntimeException("nah")), Optional.of("foo"));
}
Update: Turns out the error message was abbreviated by maven. If compiled directly with javac, the error is:
更新:原来错误消息是由 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
Also see herefor runnable test code.
另请参阅此处了解可运行的测试代码。
采纳答案by keisar
This is what solved the problem for me:
这就是为我解决问题的原因:
instead of writing
而不是写作
optional.map(this::mappingFunction).orElseThrow(() -> new BadRequestException("bla bla"));
I wrote:
我写:
optional.map(this::mappingFunction).<BadRequestException>orElseThrow(() -> new BadRequestException("bla bla"));
Adding the explicit <BadRequestException>
helps with these lambda edge cases (which are quite annoying...)
<BadRequestException>
为这些 lambda 边缘情况添加显式帮助(这很烦人......)
UPDATE: This is in case you can't update to the latest JDK version, if you can you should...
更新:这是为了防止您无法更新到最新的 JDK 版本,如果可以,您应该...
回答by Sean Van Gorder
This looks like a case of bug JDK-8054569, which doesn't affect Eclipse.
这看起来像是一个错误JDK-8054569 的案例,它不会影响 Eclipse。
I was able to narrow it down by replacing Function with Supplier and extracting the orElseThrow
method:
我能够通过用供应商替换 Function 并提取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")));
}
and then further by removing the suppliers and lambdas altogether:
然后通过完全删除供应商和 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")));
}
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
.
这实际上是一个比错误报告中的例子更清晰的例子。如果编译为 Java 8,这会显示相同的错误,但在-source 1.7
.
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).
我猜想将泛型方法返回类型传递给泛型方法参数会导致异常的类型推断失败,因此它假定类型是 Throwable 并抱怨未处理此已检查的异常类型。如果您声明bug() throws Throwable
或更改绑定到X extends RuntimeException
(因此未选中),错误就会消失。
回答by Igor Katkov
If you are trying to compile someone else's project try to upgrade to 1.8.0_92
如果您正在尝试编译其他人的项目,请尝试升级到 1.8.0_92
回答by markvgti
Similar to @keisar I could solve my problem (see maven-compiler-plugin fails to compile a file that Eclipse has no problem with) by specifying the type parameter.
与@keisar 类似,我可以通过指定类型参数来解决我的问题(请参阅maven-compiler-plugin 无法编译 Eclipse 没有问题的文件)。
However, I found it much more convenient (since I use NotFoundException
in a number of places) to simply make my exception class its own Supplier
:
但是,我发现NotFoundException
简单地使我的异常类成为它自己的更方便(因为我在许多地方使用)Supplier
:
public class NotFoundException extends RuntimeException
implements Supplier<NotFoundException> {
// Rest of the code
@Override
public NotFoundException get() {
return this;
}
}
Then you can simply do:
然后你可以简单地做:
// Distribution.rep().get(id) returns a java.util.Optional
Distribution distro = Distribution.rep().get(id).orElseThrow(
new NotUniqueException("Exception message"));