【问题标题】:Java lambda not working with full definitionJava lambda 无法使用完整定义
【发布时间】:2023-03-09 16:31:02
【问题描述】:

我正在尝试包装引发检查异常的方法。我正在按照以下网址中的步骤操作: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

wrap 函数如下所示:

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 的方式抱怨

【问题讨论】:

  • .forEach(wrap(s -&gt; testLocale(s)))。您必须包装消费者,而不是方法调用。进一步注意,您可以使用Arrays.stream(locales, 1, locales.length) .map(Object::toString) .forEach(wrap(this::testLocale))

标签: java exception lambda java-8


【解决方案1】:

您应该通过以下方式向forEach 提供一个包装好的消费者:

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

您通过s -&gt; wrap(testLocale(s)) 所做的事情是提供一个 消费者,该消费者仍然无法处理已检查的异常。

可能更容易理解的是forEach 接受具有以下方法定义的Consumer

void accept(T t); // does not define to throw the checked Exception

当您执行forEach(s -&gt; ...) 时,您正在使用的是这个Consumer::accept

另一方面,forEach(wrap(this::testLocale)); 仍将返回 Consumer,但通过接受 WrapConsumer&lt;T&gt; wrapper 作为输入,确实声明通过以下方式抛出 Exception

void accept(T t) throws Exception;

【讨论】:

  • 感谢您的快速澄清
【解决方案2】:

您只是缺少正确的 lambda 语法。您当前的代码使用 void 参数调用 wrapwrap(testLocale(s)) -(testLocale(s) 具有 void 返回类型)

您需要的正确 lambda 表达式是:

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

wrap 返回一个函数,因此您不需要延迟执行它(即不需要调用wrap 的函数)。

【讨论】:

    【解决方案3】:

    只是补充 Eugene 的回答,您期望使用 wrap() 方法将使用者作为参数,而不是返回 void 的调用方法。

    您可以通过从 testLocale 方法中删除 throws Exception 来证明这一点。

    IDE 会给你错误:

    "reason: no instance(s) of type variable(s) T exist so that void conforms to WrapConsumer<T>"
    

    您编写的类似代码(正确的消费者):

    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(wrap(l-> testLocale(l)));
    

    【讨论】:

    • 感谢您的解释
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-01-08
    • 2012-03-06
    • 2014-05-20
    • 2021-06-24
    • 2023-03-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多