在Java(或任何其他带有受控异常的语言)中,当创建您自己的异常类时,您如何决定它应该被检查还是未检查?
我的直觉是,在调用者可能能够以某种有效的方式恢复的情况下,将调用checked异常,而作为未检查的异常则更多地用于不可恢复的情况,但我对其他人的想法感兴趣。
在Java(或任何其他带有受控异常的语言)中,当创建您自己的异常类时,您如何决定它应该被检查还是未检查?
我的直觉是,在调用者可能能够以某种有效的方式恢复的情况下,将调用checked异常,而作为未检查的异常则更多地用于不可恢复的情况,但我对其他人的想法感兴趣。
当前回答
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.
其他回答
以下是我在多年开发经验后的一些看法:
Checked exception. This is a part of business use case or call flow, this is a part of application logic we expect or not expect. For example connection rejected, condition is not satisfied etc. We need to handle it and show corresponding message to user with instructions what happened and what to do next (try again later etc). I usually call it post-processing exception or "user" exception. Unchecked exception. This is a part of programming exception, some mistake in software code programming (bug, defect) and reflects a way how programmers must use API as per documentation. If an external lib/framework doc says it expects to get data in some range and non null, because NPE or IllegalArgumentException will be thrown, programmer should expect it and use API correctly as per documentation. Otherwise the exception will be thrown. I usually call it pre-processing exception or "validation" exception.
目标受众。现在让我们来谈谈目标受众或设计例外的人群(根据我的观点):
检查异常。目标受众是用户/客户。 未经检查的异常。目标受众是开发人员。换句话说,未检查异常仅是为开发人员设计的。
通过应用程序开发生命周期阶段。
受控异常被设计为在整个生产生命周期中存在,作为应用程序处理异常情况的正常和预期机制。 未检查异常被设计为只存在于应用程序开发/测试生命周期期间,所有这些异常都应该在这段时间内得到修复,并且当应用程序已经在生产环境中运行时不应该抛出。
框架通常使用未检查异常(例如Spring)的原因是框架不能确定应用程序的业务逻辑,这取决于开发人员捕捉并设计自己的逻辑。
我认为我们可以从以下几个问题来考虑例外:
为什么会发生异常?当它发生时我们能做什么
一个错误,一个bug。如方法调用空对象。
String name = null;
... // some logics
System.out.print(name.length()); // name is still null here
这种异常应该在测试期间修复。否则,它会破坏生产,你会得到一个非常严重的bug,需要立即修复。这种异常不需要检查。
通过来自外部的输入,您不能控制或信任外部服务的输出。
String name = ExternalService.getName(); // return null
System.out.print(name.length()); // name is null here
在这里,如果您希望在名称为空时继续,则可能需要检查名称是否为空,否则,您可以让它单独运行,它将在这里停止并向调用者提供运行时异常。 这种异常不需要检查。
通过来自外部的运行时异常,您不能控制或信任外部服务。
在这里,如果您希望在发生异常时继续执行,则可能需要从ExternalService捕获所有异常,否则,您可以不去管它,它将在这里停止并向调用者提供运行时异常。
通过来自外部的受控异常,您不能控制或信任外部服务。
在这里,如果您希望在发生异常时继续执行,则可能需要从ExternalService捕获所有异常,否则,您可以不去管它,它将在这里停止并向调用者提供运行时异常。
在这种情况下,我们需要知道ExternalService中发生了什么样的异常吗?这取决于:
如果您可以处理某些类型的异常,则需要捕获它们并进行处理。对其他人来说,泡一下。 如果您需要记录或响应用户特定的异常,您可以捕获它们。对其他人来说,泡一下。
来自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.
我使用的规则是:永远不要使用未经检查的异常!(或者当你看不到任何方法的时候)
有一种情况正好相反:永远不要使用受控异常。我不愿意在辩论中偏袒任何一方(双方都有很好的论据!),但相当多的专家认为,事后看来,受控例外是一个错误的决定。
对于一些讨论,请查看维基百科网站的“已检查异常的价值可疑”。另一个早期广泛争论的例子是Rod Waldhoff的博客文章。
检查例外: 如果客户端可以从异常中恢复,并希望继续,请使用受控异常。
未经检查的异常: 如果客户端在异常发生后不能做任何事情,则引发未检查的异常。
示例:如果您希望在方法a()中执行算术操作,并且基于a()的输出,则必须执行另一个操作。如果方法A()的输出为空,而您在运行时并不期望它,那么您将抛出空指针异常,即运行时异常。
请参考这里