Java中的类IOException是否是未经检查的RuntimeException?

Der*_*har 21 java exception-handling exception

您是否同意Java类的设计者java.io.IOException应该使其成为一个未经检查的运行时异常,java.lang.RuntimeException而不是仅从派生的派生异常派生java.lang.Exception

我认为该类IOException应该是一个未经检查的异常,因为应用程序几乎无法解决文件系统错误等问题.然而,当你不能抛出异常,埃利奥特·鲁斯蒂·阿罗德声称,大多数I/O错误是短暂的,所以你可以放弃之前重试I/O操作几次:

例如,IOComparator可能不会出现I/O错误,但是 - 因为许多I/O问题是暂时的 - 您可以重试几次,如清单7所示:

通常情况如此吗?Java应用程序可以纠正I/O错误还是等待系统恢复?如果是这样,那么检查IOException是合理的,但如果不是这样,则应取消选中IOException,以便业务逻辑可以将此异常的处理委托给单独的系统错误处理程序.

M. *_*sup 18

我完全不同意.对我来说,模型是正确的.RuntimeException是最常表示编程逻辑中的严重错误(例如ArrayIndexOutOfBounds,NullPointer或IllegalArgument)或运行时确定不应发生的事情(例如SecurityException).

相反地​​IOException异常及其衍生物是可能的程序的正常执行,共同逻辑期间发生合理将决定,要么这些问题应处理,或至少程序员应该意识到,他们可以发生的异常.例如,如果您的应用程序记录器无法写入其数据,那么您宁愿被迫捕获潜在的IOException并进行恢复,或者对您的应用程序可能不重要的事情会导致整个JVM崩溃,因为没有人想要抓住它未检查的异常(正如您可能已经猜到的那样,我将选择前者).

我认为在很多情况下IOException是可恢复的,或者至少程序员应该明确地意识到这种可能性,这样如果它不可恢复,系统可能会更"轻柔"地崩溃.

到目前为止,您对系统无法恢复的想法总是存在检查异常的替代方案.你总是可以让你的方法在它们的throws中声明它,抛出它们自己的运行时异常或猛烈地崩溃JVM:

public void doit() throws IOException {
  try{
  }catch(IOException e){
    // try to recover
    ...

    // can't recover
    throw e;
  }
}

public void doit() {
  try{
  }catch(IOException e){
    // try to recover
    ...

    // can't recover
    throw new RuntimeException(e);
  }
}



public void doit() {
  try{
  }catch(IOException e){
    // try to recover
    ...

    // OH NO!!!!
    System.exit(Constant.UNRECOVERABLE_IO_ERROR);
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 在http://www.oracle.com/technology/pub/articles/dev2arch/2006/11/effective-exceptions.html中,Barry Ruzek不同意:"I/O故障是一个严重但非常罕见的事件.那,你的代码通常没有任何东西可以从中恢复." 根据Ruzek的说法,许多Java库都抛出了这个异常,这表明它们遵循了第一种从"IOException"中恢复的方法.但是,如果某些方法无法从"IOException"中恢复,那么当客户端不太可能恢复时,将其抛出的重点是什么? (6认同)
  • 我不同意"非常罕见"的事件.考虑网络套接字.客户端Socket断开连接是完全合理的,如果您尝试写入或读取数据,这将导致IOException.对于恢复,我认为你需要注意你对"恢复"的定义.在套接字示例中,您可能会丢失客户端连接,但恢复可能是一个过程,例如释放被切断连接使用的资源.类似地,对于重新抛出,您可能希望将事件记录在靠近发起者的位置,但允许堆栈中较高的位置处理它. (5认同)
  • @Derek我不主张重新抛出RuntimeException.我只是提供了一个例子,说明如果出于某种原因需要行为(我无法想到它会是一个合理的例子),如何将"模拟"IOException视为未经检查.类似地,使用System.exit作为失败恢复的替代方法(也许我应该还包括对于RuntimeException示例的讽刺"// OH NO !!!!!").在任何情况下,我认为正确的策略是捕获,尝试恢复,如果可能,然后重新抛出,或从方法返回适当的值. (3认同)

nhy*_*ted 17

我知道问题已经过去了4年,但Java 8中添加了一个UncheckedIOException.

  • Java 8 API设计者必须阅读我的问题!事后看来,我应该自己发明了"UncheckIOException",并对API进行了版权保护,以便Oracle不得不向我支付许可费.:) (6认同)

Eya*_*der 5

我认为将它作为一个经过检查的例外很聪明.我认为运行时异常是错误,显然不是这种情况.有时可以通过重试进行恢复,并且一些IOException消息可以为最终用户提供信息(例如,没有写入权限,没有足够的磁盘空间等).

  • @Michael:IMO签名没有受到任何污染.就像指定返回值类型一样,您还应该指定操作的其他类型的合法结果.它具有实用和陈述的重要性. (2认同)
  • @Derek:我的意思是低级IO代码.@Eyal:这就是理论.在实践中,它会导致可怕的漏洞抽象和大量污染的API - 因为我们不是只讨论那个方法,而是讨论它与最终捕获异常的点之间的所有方法,对于调用它的每个方法.对于抛出已检查异常的每个其他方法也是如此. (2认同)

Mar*_*sey 5

可能绝大多数 IO 异常都是可恢复的 - 权限错误、驱动器空间不足、连接关闭等。我相信未经检查的异常应该用于“没有合理的方法可以从这种情况中恢复”的情况。