当前位置: 首页 > 知识库问答 >
问题:

Java8 lambda和异常

楮景明
2023-03-14

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

给定此方法

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

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

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

}

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

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

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

更新:原来错误消息是由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

另请参阅此处以获取可运行的测试代码。

共有3个答案

安建木
2023-03-14

如果您试图编译其他人的项目,请尝试升级到1.8.092

太叔昊穹
2023-03-14

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

我可以通过用Supplier替换函数并提取orelsetrow方法来缩小范围:

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

然后进一步将供应商和Lambda全部删除:

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,则会显示相同的错误,但适用于源代码1.7。

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

金瑞
2023-03-14

这就是我解决问题的原因:

而不是写作

optional.map(this::mappingFunction).orElseThrow(() -> new BadRequestException("bla bla"));

我写道:

optional.map(this::mappingFunction).<BadRequestException>orElseThrow(() -> new BadRequestException("bla bla"));

添加显式

更新:这是以防您无法更新到最新的JDK版本,如果可以,您应该...

 类似资料:
  • 如果我有一个清单,比如说 我如何才能获得一个名字不同的年龄最大的学生名单?在C#中,使用system.linq GroupBy然后比较,然后用select进行扁平化,这将非常简单,我不太确定如何在Java中实现同样的功能。

  • 我对Java8的新特性有点陌生。我正在学习如何通过条目过滤地图。我已经看了这个教程和这个帖子我的问题,但我无法解决。

  • 奇怪的是,标记为“OK”的行编译得很好,但标记为“Error”的行失败了。它们看起来基本上是一样的。

  • 当试图在文件中运行lambda时,我遇到了一个问题:才允许使用。 我的设置: 在Intellij IDEA的项目结构中,我将项目SDK和项目语言设置为Java8. 模块语言级别为8-Lambdas、类型注释等 使用和 项目字节码版本设置为1.8 Jetty的最新版本(V9.4.31.x) 项目使用插件,在中将 和 设置为1.8

  • 给定一个元素列表,我想获取具有给定属性的元素并将其从列表中删除。我找到的最佳解决方案是: 是否可以在lambda表达式中组合get和删除?

  • 异步操作在线程中执行,与主应用程序线程分开。当应用程序调用方法异步执行操作时,应用程序可以在异步方法执行其任务时继续执行。 示例 下面通过一个例子来理解这个概念。在示例程序中使用IO库接受用户输入。 是一种同步方法。它将阻止执行函数调用之后的所有指令,直到方法完成执行。 等待输入。它停止执行并且在收到用户输入之前不再执行任何操作。 以上示例将产生以下输出 - 在计算中,当某个事件在继续之前等待事件