在Java(或任何其他带有受控异常的语言)中,当创建您自己的异常类时,您如何决定它应该被检查还是未检查?
我的直觉是,在调用者可能能够以某种有效的方式恢复的情况下,将调用checked异常,而作为未检查的异常则更多地用于不可恢复的情况,但我对其他人的想法感兴趣。
在Java(或任何其他带有受控异常的语言)中,当创建您自己的异常类时,您如何决定它应该被检查还是未检查?
我的直觉是,在调用者可能能够以某种有效的方式恢复的情况下,将调用checked异常,而作为未检查的异常则更多地用于不可恢复的情况,但我对其他人的想法感兴趣。
当前回答
检查例外: 如果客户端可以从异常中恢复,并希望继续,请使用受控异常。
未经检查的异常: 如果客户端在异常发生后不能做任何事情,则引发未检查的异常。
示例:如果您希望在方法a()中执行算术操作,并且基于a()的输出,则必须执行另一个操作。如果方法A()的输出为空,而您在运行时并不期望它,那么您将抛出空指针异常,即运行时异常。
请参考这里
其他回答
在任何一个足够大的系统上,有很多层,检查异常是无用的,因为无论如何,您需要一个架构级策略来处理异常将如何处理(使用故障屏障)。
使用受控异常,您的错误处理策略是微管理的,在任何大型系统上都无法承受。
大多数情况下,您不知道错误是否“可恢复”,因为您不知道API的调用者位于哪一层。
假设我创建了一个StringToInt API,用于将整数的字符串表示形式转换为Int。如果API是用“foo”字符串调用的,我必须抛出检查异常吗?它可以恢复吗?我不知道,因为在他的层中,我的StringToInt API的调用者可能已经验证了输入,如果抛出这个异常,它要么是一个错误,要么是一个数据损坏,它是不可恢复的这一层。
在这种情况下,API的调用者不想捕获异常。他只想让异常“冒出来”。如果我选择了一个受控异常,这个调用者将有大量无用的catch块,只能人为地重新抛出异常。
大多数时候,什么是可恢复的取决于API的调用者,而不是API的编写者。API不应该使用受控异常,因为只有未受控异常才允许选择捕获或忽略异常。
You can call it a checked or unchecked exception; however, both types of exception can be caught by the programmer, so the best answer is: write all of your exceptions as unchecked and document them. That way the developer who uses your API can choose whether he or she wants to catch that exception and do something. Checked exceptions are a complete waste of everyone's time and it makes your code a shocking nightmare to look at. Proper unit testing will then bring up any exceptions that you may have to catch and do something with.
这里有一个非常简单的方法来解决你的“受控/未受控”困境。
规则1:将未检查异常视为代码执行前的可测试条件。 例如……
x.doSomething(); // the code throws a NullPointerException
其中x为空… 代码应该有以下内容
if (x==null)
{
//do something below to make sure when x.doSomething() is executed, it won’t throw a NullPointerException.
x = new X();
}
x.doSomething();
规则2:将检查异常视为代码执行时可能出现的不可测试条件。
Socket s = new Socket(“google.com”, 80);
InputStream in = s.getInputStream();
OutputStream out = s.getOutputStream();
在上面的例子中,URL (google.com)可能由于DNS服务器宕机而不可用。即使在DNS服务器工作并将“google.com”名称解析为IP地址的瞬间,如果连接到google.com,在任何时候,网络都可能瘫痪。你不能在读写流之前一直测试网络。
有时候,在我们知道是否存在问题之前,代码必须执行。通过强迫开发人员以这种方式编写代码,迫使他们通过检查异常来处理这些情况,我不得不向发明了这个概念的Java创造者致敬。
一般来说,几乎所有的Java api都遵循上述2条规则。如果尝试写入文件,磁盘可能会在完成写入之前被填满。可能是其他进程导致磁盘已满。根本没有办法测试这种情况。对于那些随时与硬件交互的人来说,使用硬件可能会失败,受控异常似乎是解决这个问题的一个优雅的解决方案。
这是一个灰色地带。在需要许多测试的情况下(一个带有大量&&和||的令人震惊的if语句),抛出的异常将是一个CheckedException,因为要正确处理它太痛苦了——你不能简单地说这个问题是一个编程错误。如果测试少于10个(例如' If (x == null) '),那么程序员错误应该是UncheckedException。
与语言口译员打交道时,事情变得有趣起来。根据上面的规则,语法错误应该被认为是一个检查或未检查的异常?我认为,如果语言的语法可以在执行之前进行测试,那么它应该是UncheckedException。如果无法测试该语言——类似于程序集代码在个人计算机上的运行方式,那么语法错误应该是一个已检查异常。
The 2 rules above will probably remove 90% of your concern over which to choose from. To summarize the rules, follow this pattern… 1) if the code to be execute can be tested before it’s executed for it to run correctly and if an Exception occurs — a.k.a. a programmer error, the Exception should be an UncheckedException (a subclass of RuntimeException). 2) if the code to be executed can not be tested before it’s executed for it to run correctly, the Exception should be a Checked Exception (a subclass of Exception).
来自Java学习者:
When an exception occurs, you have to either catch and handle the exception, or tell compiler that you can't handle it by declaring that your method throws that exception, then the code that uses your method will have to handle that exception (even it also may choose to declare that it throws the exception if it can't handle it). Compiler will check that we have done one of the two things (catch, or declare). So these are called Checked exceptions. But Errors, and Runtime Exceptions are not checked for by compiler (even though you can choose to catch, or declare, it is not required). So, these two are called Unchecked exceptions. Errors are used to represent those conditions which occur outside the application, such as crash of the system. Runtime exceptions are usually occur by fault in the application logic. You can't do anything in these situations. When runtime exception occur, you have to re-write your program code. So, these are not checked by compiler. These runtime exceptions will uncover in development, and testing period. Then we have to refactor our code to remove these errors.
我同意将未检查异常作为规则的偏好,特别是在设计API时。调用方总是可以选择捕获记录在案的、未检查的异常。你只是没有必要强迫打电话的人。
I find checked exceptions useful at the lower-level, as implementation detail. It often seems like a better flow of control mechanism than having to manage a specified error "return code". It can sometimes help see the impact of an idea for a low level code change too... declare a checked exception downstream and see who would need to adjust. This last point doesn't apply if there are a lot of generic: catch(Exception e) or throws Exception which is usually not too well-thought out anyway.