我正在使用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);
}
};
}
}
所以我可以在这种情况下使用它:
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);
}))
它会将任何已检查的异常包装为未选中,但我知道如果方法抛出多个异常,它将擦除为Throwable,我将在简单的情况下使用它。
这是好主意,还是我可能遇到隐藏的障碍?
更新:重新运行RuntimeExceptions。
此外,我在jOOL中找到了更清晰的解决方案,处理InterruptedException,如果忽略它会导致不一致的行为: https://github.com/jOOQ/jOOL/blob/master/src/main/java/org/jooq/lambda/Unchecked.java
答案 0 :(得分:0)
如果ClassCastException
以外的其他内容被抛出,您将获得IOException
,因为您正在捕获所有Throwable
并将其传递到UncheckedIOException
构造函数中,只需要IOException
作为参数。由于在函数类型中捕获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);
}
};
}
}