小编典典

我该如何以安全且可读的方式处理一个我永远不会抛出的IOException?

java

“可能出错的事情和不可能出错的事情之间的主要区别是,当一件不可能出错的事情出错时,通常发现根本无法修理。” -道格拉斯·亚当斯

我有一类FileItems。FileItems构造函数获取一个文件,如果该文件不存在,则抛出异常(FileNotFoundException)。该类的其他方法也涉及文件操作,因此可以抛出FileNotFoundException。我想找到一个更好的解决方案。一种不需要其他程序员处理所有这些极不可能的FileNotFoundExceptions的解决方案。

问题事实:

  1. 已检查文件存在,但极有可能的情况是,由于现实的一些重大缺陷,可能在调用此方法之前删除了文件。
  2. 由于1发生的可能性极不相同且无法恢复,因此我希望定义一个未经检查的异常。
  3. 已经发现该文件存在,从而迫使其他程序员编写代码并捕获检查到的FileNotFoundException看起来乏味且无用。该程序此时应该完全失败。例如,总是有机会使计算机着火,但是没有人会疯狂地强迫其他程序员将其作为受检查的异常来处理
  4. 我不时遇到这种Exception问题,每次遇到此问题(我的旧解决方案)时都定义自定义未经检查的异常(我的旧解决方案)很累,并且增加了代码膨胀。

目前的代码如下所示

 public Iterator getFileItemsIterator() {
    try{
        Scanner sc = new Scanner(this.fileWhichIsKnowToExist);
        return new specialFileItemsIterator(sc);        
       } catch (FileNotFoundException e){ //can never happen}

    return null;
 }

如何在不定义自定义未经检查的FileNotFoundException的情况下更好地做到这一点?有什么方法可以将checkedException强制转换为uncheckException吗?


阅读 209

收藏
2020-12-03

共1个答案

小编典典

处理此问题的通常模式是异常链接。您只需将FileNotFoundException包装在RuntimeException中:

catch(FileNotFoundException e) {
    throw new RuntimeException(e);
}

此模式不仅适用于在特定情况下(例如您的情况)无法发生异常的情况,而且适用于您无意或无意真正处理该异常的情况(例如数据库链接失败)。

编辑 :提防这种外观相似的反模式,我在野外经常看到的情况:

catch(FileNotFoundException e) {
    throw new RuntimeException(e.getMessage());
}

这样,您就丢弃了原始堆栈跟踪中的所有重要信息,这通常会使问题难以跟踪。

另一个编辑: 正如ThorbjørnRavn
Andersen在他的答复中正确指出的那样,在注释中,或者甚至更好地,将异常链接到异常消息中来说明为什么要链接异常:

catch(FileNotFoundException e) {
    throw new RuntimeException(
        "This should never happen, I know this file exists", e);
}
2020-12-03