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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2624145/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 22:04:42  来源:igfitidea点击:

Should class IOException in Java have been an unchecked RuntimeException?

javaexceptionexception-handling

提问by Derek Mahar

Do you agree that the designers of Java class java.io.IOExceptionshould have made it an unchecked run-time exception derived from java.lang.RuntimeExceptioninstead of a checked exception derived only from java.lang.Exception?

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

I think that class IOExceptionshould have been an unchecked exception because there is little that an application can do to resolve problems like file system errors. However, in When You Can't Throw An Exception, Elliotte Rusty Haroldclaims that most I/O errors are transient and so you can retry an I/O operation several times before giving up:

我认为该类IOException应该是未经检查的异常,因为应用程序几乎无法解决文件系统错误等问题。然而,在When You Can't Throw An Exception 中Elliotte Rusty Harold声称大多数 I/O 错误都是暂时的,因此您可以在放弃之前重试一次 I/O 操作:

For instance, an IOComparator might not take an I/O error lying down, but — because many I/O problems are transient — you can retry a few times, as shown in Listing 7:

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

Is this generally the case? Can a Java application correct I/O errors or wait for the system to recover? If so, then it is reasonable for IOException to be checked, but if it is not the case, then IOException should be unchecked so that business logic can delegate handling of this exception to a separate system error handler.

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

采纳答案by M. Jessup

I completely disagree. To me the model is correct. A RuntimeException is one which most typically denotes a serious error in the logic of the programming (such as ArrayIndexOutOfBounds, NullPointer, or IllegalArgument) or something that the runtime has otherwise determined really shouldn't be happening (such as SecurityException).

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

Conversely IOException and its derivatives are exceptions that could reasonably occur during normal execution of a program, and common logic would dictate that either those problems should be dealt with, or at least the programmer should be aware that they can occur. For example with Files if your application logger can't write its data would you rather be forced to catch a potential IOException and recover, or have something that may not be critical to your app bring down the whole JVM because no one thought to catch the unchecked Exception (as you may have guessed, I'll choose the former).

相反,IOException 及其派生类是在程序正常执行期间可能合理发生的异常,而通用逻辑将规定要么应该处理这些问题,要么至少程序员应该意识到它们可能会发生。例如对于文件,如果您的应用程序记录器无法写入其数据,您宁愿被迫捕获潜在的 IOException 并进行恢复,或者有一些可能对您的应用程序不重要的东西导致整个 JVM 宕机,因为没有人想到捕获unchecked Exception(你可能已经猜到了,我会选择前者)。

I think that there are many situations in which an IOException is either recoverable, or at the least the programmer should be explicitly aware of the potential so that if it is not recoverable the system might be able to crash more "gently".

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

As far your thought of if the system can not recover there are always alternatives with a checked exception. You can always have your methods declare it in their throws, throw a runtime exception of their own or crash the JVM violently:

就您的想法而言,如果系统无法恢复,总会有带有已检查异常的替代方案。你总是可以让你的方法在它们的 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);
  }
}

回答by nhylated

I know it has been 4 years since this question was asked but an UncheckedIOExceptionwas added in Java 8.

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

回答by Eyal Schneider

I think it is clever to leave it a checked exception. I regard runtime exceptions as bugs, and this is clearly not the case. Recovery by retry is sometimes possible, and also some IOException messages can be informative to the end user (e.g. no permissions to write, not enough disk space, etc).

我认为将其保留为已检查的异常是明智的。我将运行时异常视为bugs,而这显然不是这种情况。通过重试进行恢复有时是可能的,并且一些 IOException 消息也可以为最终用户提供信息(例如,没有写入权限,没有足够的磁盘空间等)。

回答by Mark Bessey

Probably the vast majority of IO exceptions are recoverable - permissions errors, lack of space on the drive, connection closed, etc, etc. I believe unchecked exceptions are supposed to be used for "there's no reasonable way to recover from this" sorts of situations.

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

回答by supercat

In a well-designed exception framework, a distinction should be made between exceptions which are to some extent "expected" and those which are not. Java attempts to use checked versus unchecked exceptions for this. By that standard, IOException should be a checked exception.

在设计良好的例外框架中,应该区分在某种程度上“预期”的例外和非“预期”的例外。Java 尝试为此使用受检异常与未受检异常。按照这个标准,IOException 应该是一个检查异常。

A fundamental problem, though, is that oftentimes code will be written with a (perhaps reasonable) expectation that a certain exception will not occur, and nothing can usefully be done to handle it if it does. If a method is declared as throwing a particular checked exception, Java allows its caller to ignore the exception if it declares itself as throwing that exception, but there's no means by which a method or code block can specify that certain exceptions from called methods are not expected to occur. A common anti-pattern is:

然而,一个基本的问题是,编写代码时通常会期望(也许是合理的)不会发生某个异常,如果发生,则无法采取任何有用的措施来处理它。如果一个方法被声明为抛出一个特定的检查异常,Java 允许它的调用者在它声明自己抛出该异常时忽略该异常,但是方法或代码块无法指定来自被调用方法的某些异常不是预计会发生。一个常见的反模式是:

try
{
  methodThatsDeclaredAsThrowingFooExceptionButWont()
}
catch FooException Ex
{
  // Never going to happen
}

The apparent assumption is that since the method won't throw FooException and the only reason the catchis there is to make the compiler happy, there's no reason for the catchto do anything. Insidious, because if a FooExceptiondoes get thrown, for whatever reason, it will go undetected.

明显的假设是,由于该方法不会抛出 FooException 并且存在的唯一原因catch是让编译器满意,因此没有理由catch做任何事情。阴险,因为如果 aFooException确实被抛出,无论出于何种原因,它都不会被发现。

An alternative is for a method which calls methodThatsDeclaredAsThrowingFooExceptionButWont to declare itself as throws FooExceptionor throws Exception, but that isn't really appropriate either. If a method which is not expected to throw a FooExceptiondoes, the system state is apt to be different from what it would be expected when a FooExceptionis thrown.

另一种方法是调用 methodThatsDeclaredAsThrowingFooExceptionButWont 将自身声明为throws FooExceptionor 的方法throws Exception,但这也不太合适。如果不期望抛出 a 的方法FooException确实发生了,则系统状态很容易与抛出 a 时预期的状态不同FooException

For example, suppose one attempts to load a document, but the document-load routine needs to read some non-document-specific translation tables which are supposed to be stored at a fixed location; if that attempt fails, having the IOExceptionpercolate up to the caller would imply that there was a problem loading the document being loaded. If the load-document routine isn't prepared to sensibly handle the possibility that the load-translation-tables routine might fail, such failure shouldn't percolate up the same way as would an IOExceptionthat occurred while actually loading the document.

例如,假设一个人试图加载一个文档,但是文档加载例程需要读取一些应该存储在固定位置的非文档特定的翻译表;如果该尝试失败,则将IOException渗透传递给调用者将意味着加载正在加载的文档时出现问题。如果加载文档例程没有准备好明智地处理加载转换表例程可能失败的可能性,那么这种失败不应该像IOException实际加载文档时发生的那样渗透。

The proper remedy would not be for IOExceptionto be an unchecked exception, but rather for there to be a declarative means by which code could indicate that one or more kinds of checked exceptions should not be allowed to percolate out of a certain block from methods called thereby, but should instead be wrapped in some other exception type (e.g. RuntimeException).

正确的补救措施不是成为IOException未经检查的异常,而是有一种声明性的方式,代码可以通过这种方式表明不应允许一种或多种类型的检查异常从特定块中渗出,从而调用方法,但应该包装在其他一些异常类型中(例如 RuntimeException)。

回答by Pyrolistical

No because you can recover from some IOExceptions. Most notable ones are low level indexed reads and writes. If it fails, sometimes you can just retry without harm.

不,因为您可以从某些 IOExceptions 中恢复。最值得注意的是低级索引读取和写入。如果失败,有时您可以重试而不会造成伤害。