Java 8 Lambda 函数会引发异常吗?

2022-08-31 04:15:03

我知道如何创建对具有参数并返回一个的方法的引用,它是:Stringint

Function<String, Integer>

但是,如果函数引发异常,则这不起作用,例如它被定义为:

Integer myMethod(String s) throws IOException

如何定义此引用?


答案 1

您需要执行以下操作之一。

  • 如果是你的代码,那么定义你自己的功能接口来声明已检查的异常:

    @FunctionalInterface
    public interface CheckedFunction<T, R> {
       R apply(T t) throws IOException;
    }
    

    并使用它:

    void foo (CheckedFunction f) { ... }
    
  • 否则,请包装在不声明已检验异常的方法中:Integer myMethod(String s)

    public Integer myWrappedMethod(String s) {
        try {
            return myMethod(s);
        }
        catch(IOException e) {
            throw new UncheckedIOException(e);
        }
    }
    

    然后:

    Function<String, Integer> f = (String t) -> myWrappedMethod(t);
    

    艺术

    Function<String, Integer> f =
        (String t) -> {
            try {
               return myMethod(t);
            }
            catch(IOException e) {
                throw new UncheckedIOException(e);
            }
        };
    

答案 2

您实际上可以使用处理异常的新接口进行扩展(等等) - 使用Java 8的默认方法ConsumerFunction

考虑这个接口(扩展):Consumer

@FunctionalInterface
public interface ThrowingConsumer<T> extends Consumer<T> {

    @Override
    default void accept(final T elem) {
        try {
            acceptThrows(elem);
        } catch (final Exception e) {
            // Implement your own exception handling logic here..
            // For example:
            System.out.println("handling an exception...");
            // Or ...
            throw new RuntimeException(e);
        }
    }

    void acceptThrows(T elem) throws Exception;

}

然后,例如,如果您有一个列表:

final List<String> list = Arrays.asList("A", "B", "C");

如果你想用一些引发异常的代码来使用它(例如 with ),你传统上会设置一个 try/catch 块:forEach

final Consumer<String> consumer = aps -> {
    try {
        // maybe some other code here...
        throw new Exception("asdas");
    } catch (final Exception ex) {
        System.out.println("handling an exception...");
    }
};
list.forEach(consumer);

但是有了这个新接口,你可以用lambda表达式实例化它,编译器不会抱怨:

final ThrowingConsumer<String> throwingConsumer = aps -> {
    // maybe some other code here...
    throw new Exception("asdas");
};
list.forEach(throwingConsumer);

或者甚至只是把它投射得更简洁!

list.forEach((ThrowingConsumer<String>) aps -> {
    // maybe some other code here...
    throw new Exception("asda");
});

更新:看起来榴莲有一个非常好的实用程序库部分,称为Errors,可用于以更大的灵活性解决此问题。例如,在我上面的实现中,我已经明确定义了错误处理策略( or ),而 Durian 的错误允许您通过一大套实用程序方法动态应用策略。感谢您的分享,@NedTwigg!System.out...throw RuntimeException

示例用法:

list.forEach(Errors.rethrow().wrap(c -> somethingThatThrows(c)));

推荐