终端操作(例如 forEach)可以重新抛出已检查的异常吗?
Posted
技术标签:
【中文标题】终端操作(例如 forEach)可以重新抛出已检查的异常吗?【英文标题】:Can a terminal operation (e.g. forEach) rethrow checked exceptions? 【发布时间】:2014-03-08 13:45:05 【问题描述】:我有一个方法可以删除一些文件:
void deepDelete(Path root)
Files.walk(root)
.filter(p -> !Files.isDirectory(p))
.forEach(p -> try Files.delete(p);
catch (IOException e) /* LOG */
);
try/catch 块会降低操作的可读性,尤其是与使用方法引用相比:
void deepDelete(Path root) throws IOException
Files.walk(root)
.filter(p -> !Files.isDirectory(p))
.forEach(Files::delete); //does not compile
很遗憾,该代码无法编译。
有没有办法应用在终端操作中引发检查异常并简单地“重新引发”任何异常的操作?
我知道我可以编写一个将已检查异常转换为未检查异常的包装器,但如果可能的话,我宁愿坚持使用 JDK 中的方法。
【问题讨论】:
显然,Java 8 远离了 checked 异常。几乎所有新引入的异常都是unchecked,而新引入的方法使用unchecked异常,例如Files.list 抛出 UncheckedIOException。 @nosid: 看不到已检查异常的总体趋势。只有 流操作 会抛出UncheckedIOException
,原因与此问题中讨论的相同:流 API 不允许抛出已检查的 IOException
。如果IOException
在构造流之前发生,则通常会检查它。
【参考方案1】:
据我所知:没有。我使用this techempower article 作为我的 java8 指南,它非常明确(参见标题为“异常透明度”的部分)。
【讨论】:
【参考方案2】:如果你声明这个方法:
@SuppressWarnings("unchecked")
static <T extends Throwable> RuntimeException sneakyThrow(Throwable t) throws T
throw (T)t;
那么你可以这样做:
try
Files.delete(p);
catch (IOException e)
throw sneakyThrow(e);
这绕过检查的异常规则并抛出原始IOException
而不进行包装,尽管您仍然必须捕获它并重新抛出。我并不是说这是一个好主意,而是一个的主意。
【讨论】:
以上是关于终端操作(例如 forEach)可以重新抛出已检查的异常吗?的主要内容,如果未能解决你的问题,请参考以下文章
AppDomain.UnhandledException 自动重新抛出已处理的异常
Spring Security 部署失败:生命周期方法 [initialize] 不得抛出已检查异常