在Stream API中使用checked decorator函数是否是一个很好的解决方案?

aga*_*kiy 6 java lambda exception function java-stream

我正在使用Java 8 Stream API,并且我们知道它不支持java.util.function中任何功能接口内的已检查异常.

我通常必须在流操作中使用带有已检查异常的方法,并且我已经编写了CheckedFunction装饰器以在这些操作中使用:

import java.util.function.BiFunction;
import java.util.function.Function;

public interface CheckedFunction<T, R, E extends Throwable> {

    R apply(T t) throws E;

    static <T, R, CE extends Throwable, UCE extends RuntimeException> Function<T, R> checked(
            CheckedFunction<T, R, CE> checked, Function<CE, UCE> exceptionHandler) {
        return (t) -> {
            try {
                return checked.apply(t);
            }
            catch (RuntimeException | Error e) {
                throw e;
            }
            catch (Throwable e) {
                // can't catch - compiler error
                if (e instanceof InterruptedException) {
                    Thread.currentThread().interrupt();
                }
                throw exceptionHandler.apply((CE) e);
            }
        };
    }
}
Run Code Online (Sandbox Code Playgroud)

所以我可以在这种情况下使用它:

entities.stream()
        .map(checked((entity) -> someResultChecked(entity), // throws IOException
                     (entity, e) -> { // e is of type IOException
                         log.error("exception during checked method of " + entity, e);
                         return new UncheckedIOException(e);
                     }))
        .map(checked((entity) -> saveToDb(entity), // throws SQLException
                     (entity, e) -> { // e is of type SQLException
                         log.error("exception during saving " + entity, e);
                         return new UncheckedSQLException(e);
                     }))
        .map(checked((entity) -> manyExceptionMethod(entity), // throws IOException, SQLException
                     (entity, e) -> { // e is of type Throwable
                         return new RuntimeException(e);
                     }))
Run Code Online (Sandbox Code Playgroud)

它将任何已检查的异常包装为未选中,但我知道如果方法抛出多个异常,它将擦除为Throwable,我将在简单的情况下使用它.

这是好主意,还是我可能遇到隐藏的障碍?

更新:重新运行RuntimeExceptions.

此外,我在jOOL中找到了更清晰的解决方案,处理InterruptedException,如果忽略它会导致不一致的行为:https: //github.com/jOOQ/jOOL/blob/master/src/main/java/org/jooq/lambda/Unchecked的.java

Han*_*k D 0

ClassCastException如果除了 an 以外的任何东西IOException被抛出,您将得到 a ,因为您捕获了所有Throwable并将它们传递到UncheckedIOException构造函数中,该构造函数只接受 anIOException作为参数。由于IOException在函数类型中进行捕获是一种常见的需求,因此最好保持简单并仅针对该已检查的异常创建一个,而不是尝试概括。我想您很少需要重复代码来对其他检查的异常执行相同的操作。

@FunctionalInterface
public interface CheckedIOFunction<T,R> {

    R apply(T t) throws IOException;

    static <T, R> Function<T, R> toUnchecked(CheckedIOFunction<T, R> function) {
        return t -> {
            try {
                return function.apply(t);
            } catch (IOException ioe) {
                throw new UncheckedIOException(ioe);
            }
        };
    }
}
Run Code Online (Sandbox Code Playgroud)

  • @Monk3D:`CE`可以推断为目标方法声明的已检查异常,并且实际上,目标方法不能抛出其他已检查异常。尽管如此,“catch(Throwable)”也会捕获所有*未经检查的*异常,即“RuntimeException”和“Error”,所以这个答案有道理。正确的解决方案是先将它们整理出来: `catch(RuntimeException|Error unchecked) { throw unchecked; } catch(Throwable checkedException) { throw exceptionHandler.apply(t, (CE)checkedException); } }` 但请注意,无法表达“CE”必须是受检查异常的结果要求。 (2认同)