猿问

Java lambda 不适用于完整定义

我正在尝试包装抛出已检查异常的方法。我正在按照此网址中的步骤操作:https ://www.rainerhahnekamp.com/en/ignoring-exceptions-in-java/


有趣的是,当我这样写代码时:


IntStream.range(1, locales.length)

            .mapToObj(i -> locales[i].toString())

            .forEach(wrap(this::testLocale));

它工作正常但是当我这样写时:


IntStream.range(1, locales.length)

            .mapToObj(i -> locales[i].toString())

            .forEach(s -> wrap(testLocale(s)));

Intellij 抱怨“未处理的异常:java.lang.Exception”


这里 testLocale 看起来像这样:


void testLocale(String s) throws Exception

包装函数如下所示:


public static <T> Consumer<T> wrap(WrapConsumer<T> wrapper) {

    return t -> {

        try {

            wrapper.accept(t);

        } catch(Exception exception) {

            throw new RuntimeException(exception);

        }

    };

}

而 WrapConsumer 是带有 Consumer 签名的函数接口:


@FunctionalInterface

public interface WrapConsumer<T> {

   void accept(T t) throws Exception;

}

我正在努力理解为什么 Intellij 根据我编写 lambda 的方式抱怨


繁星淼淼
浏览 148回答 3
3回答

斯蒂芬大帝

您应该通过以下方式提供包装好的消费者forEach:.forEach(wrap(this::testLocale));您正在做s -> wrap(testLocale(s))的是提供一个仍然无法处理已检查异常的新消费者。可能更容易理解的是forEach接受Consumer具有以下方法定义的 a:void&nbsp;accept(T&nbsp;t);&nbsp;//&nbsp;does&nbsp;not&nbsp;define&nbsp;to&nbsp;throw&nbsp;the&nbsp;checked&nbsp;Exception当你这样做的时候,你正在使用forEach(s -> ...)的就是这个。Consumer::accept另一方面,forEach(wrap(this::testLocale));它将返回一个Consumer静止图像,但是通过接受一个WrapConsumer<T> wrapper确实声明通过以下方式抛出的Exception输入作为输入:void&nbsp;accept(T&nbsp;t)&nbsp;throws&nbsp;Exception;

慕勒3428872

只是补充 Eugene 的回答,您期望方法 wrap() 将消费者作为参数,而不是返回 void 的调用方法。您可以通过从 testLocale 方法中删除 throws Exception 来证明这一点。IDE 会给你错误:"reason:&nbsp;no&nbsp;instance(s)&nbsp;of&nbsp;type&nbsp;variable(s)&nbsp;T&nbsp;exist&nbsp;so&nbsp;that&nbsp;void&nbsp;conforms&nbsp;to&nbsp;WrapConsumer<T>"您编写的代码(正确的消费者)的类似代码:IntStream.range(1,&nbsp;locales.length) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.mapToObj(i&nbsp;->&nbsp;locales[i].toString()) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.forEach(wrap(this::testLocale));将会:IntStream.range(1,&nbsp;locales.length) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.mapToObj(i&nbsp;->&nbsp;locales[i].toString()) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.forEach(wrap(l->&nbsp;testLocale(l)));

四季花海

您只是缺少正确的 lambda 语法。您当前的代码正在调用&nbsp;wrap一个void参数:-(wrap(testLocale(s))具有testLocale(s)void 返回类型)您需要的正确 lambda 表达式是:.forEach(wrap(s&nbsp;->&nbsp;testLocale(s)));wrap返回一个函数,因此您不需要延迟执行它(即,不需要调用 的函数wrap)。
随时随地看视频慕课网APP

相关分类

Java
我要回答