Java 中的类 IOException 应该是一个未经检查的 RuntimeException 吗?

2022-09-01 13:43:55

您是否同意 Java 类的设计者应该将其设置为派生的未经检查的运行时异常,而不是仅派生的已检查异常?java.io.IOExceptionjava.lang.RuntimeExceptionjava.lang.Exception

我认为该类应该是一个未经检查的异常,因为应用程序在解决文件系统错误等问题方面几乎无能为力。但是,在《当你不能抛出异常时》中,Elliotte Rusty Harold声称大多数I / O错误都是暂时性的,因此您可以在放弃之前多次重试I / O操作:IOException

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

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


答案 1

我知道自从提出这个问题以来已经过去了4年,但是在Java 8中添加了UncheckEDIOException


答案 2

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

相反,IOException及其衍生物是在程序正常执行期间可能合理发生的异常,并且通用逻辑将指示应该处理这些问题,或者至少程序员应该意识到它们可能发生。例如,对于 Files,如果您的应用程序记录器无法写入其数据,您是否宁愿被迫捕获潜在的 IOException 并恢复,或者让一些可能对您的应用程序不重要的东西导致整个 JVM 关闭,因为没有人想到要捕获未经检查的异常(正如您可能已经猜到的那样,我会选择前者)。

我认为在很多情况下,IOException要么是可恢复的,要么至少程序员应该明确意识到这种可能性,这样如果它不可恢复,系统可能能够更“温和地”崩溃。

就您认为如果系统无法恢复,则始终存在选中异常的替代方案。你总是可以让你的方法在他们的抛射中声明它,抛出自己的运行时异常或暴力地崩溃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);
  }
}

推荐