什么时候可以捕获一个RuntimeException
在最近的一个项目中,我build议在testing用例代码中捕获一个RuntimeException并logging下来。 代码处理来自数据库的一系列input,并且我不希望testing因任何input失败而停止(空值,非法参数等)。 不用说,我的build议引发了激烈的讨论。
捕捉任何types的RuntimeException是否可以接受? 如果是,那么可以捕获RuntimeExceptions的其他情况是什么?
您捕获RuntimeException
的原因与您捕获任何exception的情况相同:您计划对此执行任何操作。 也许你可以纠正引起exception的东西。 也许你只是想重新抛出一个不同的exceptiontypes。
但是,捕捉和忽略任何例外是非常糟糕的做法。
除非你能纠正一个RuntimeException,否则你不想捕捉它…
…从开发者的angular度来看只有真实的….
你必须赶上所有的例外,才能达到用户界面,让你的用户伤心 。 这意味着在“最高级别”上你想要捕捉到任何进一步发生的事情。 然后你可以让用户知道有一个问题,同时采取措施通知开发人员,如发出警报邮件或任何…
它基本上被认为是一个数据/编程错误,不能预见,因此,你想改善软件的未来版本,同时把用户的手,并以受控的方式继续前进…
RuntimeException旨在用于程序员错误。 因此不应该被抓到。 有几种情况应该是:
-
你正在调用来自第三方的代码,当你抛出exception的时候你无法控制它。 我会争辩说,你应该在个案的基础上做这个,并在你自己的类中包装第三方代码的使用,所以你可以传回非运行时exception。
-
你的程序不能崩溃,并留下堆栈跟踪供用户查看。 在这种情况下,它应该绕过任何线程和事件处理代码。 当这种exception发生时,程序也许应该退出。
在你的具体情况下,我将不得不质疑为什么你在testing中发生RuntimeException – 你应该修复它们而不是解决它们。
所以你应该保证你的代码只在抛出程序的时候抛出RuntimeException。 当你想logging并退出时,你应该只捕获RuntimeException。 这与RuntimeExceptions的意图是一致的。
你可以看看这个讨论的其他原因,人们给予…我个人还没有find一个令人信服的理由,但答案。
几年前,我们编写了一个控制系统框架,并且Agent对象捕获了运行时exception,如果可以并继续logging它们。
是的,我们在框架代码中捕获了包括OutOfMemory在内的运行时exception(并且强制执行一个GC,令人惊讶的是,即使运行相当多的代码也是如此。)我们的代码涉及到真实的世界。 并且由于微小的舍入误差,有时候一个非数字也会进入,而且它也可以应付。
所以在框架/“不能退出”的代码,我认为这是可以理解的。 当它工作,这是非常酷的。
代码非常稳固,但它运行的是硬件,有时硬件往往会给出棘手的答案。
它被devise为一次运行数月,而无需人工干预。 它在我们的testing中运行得非常好。
作为错误恢复代码的一部分,可以使用UPS在N分钟内closures并在M分钟内开启的能力来重新启动整个build筑物。
有时硬件故障需要重新启动:)
如果我记得,在一次不成功的电力周期后的最后一招是发送一封邮件给它的所有者,说:“我试图修复自己,我不能;问题是在子系统XYZ”,并包括一个链接,以提高支持回电给我们。
不幸的是,这个项目在能够自我意识之前就已经被封装了:)>
在我的代码中,99%的exception来自runtime_exception。
我发现exception的原因是:
- 抓住日志和修复问题。
- 捕获日志并生成更具体的exception并抛出
- 抓住日志并重新抛出 。
- 捕获日志和杀戮操作(抛弃exception)
- 用户/请求发起的操作失败。
例如,一个HTTP请求处理程序。 我宁愿要求的操作而不是把服务关掉。 (虽然最好处理程序有足够的意义返回500错误代码。) - testing用例通过/失败,例外。
- 所有的exception不在主线程中。
允许exception转义线程通常logging不准确,但通常会导致程序终止(没有堆栈解除)。
- 用户/请求发起的操作失败。
就我个人而言,我总是被告知要捕获所有的 RuntimeException; 但是,您也想对exception做些事情,例如运行故障安全,或者可能只是通知用户发生了错误。
我所从事的最后一个Java项目也有类似的方法,至less我们会logging这个exception,这样如果一个用户调用了一个bug,我们就可以找出发生了什么事情,并查看错误发生的位置。
编辑1:正如kdgregory所说,捕捉和忽略是两回事,一般来说,人们反对后者:-)
我们都知道检查exception和RuntimeExceptions
是两类exception。 总是build议我们处理(或者试一试或者抛出)检查的exception,因为它们是编程条件,不幸的是程序员不能自己做任何事情; 像FileNotFoundException
它不是程序员把文件放在用户的驱动器,如果程序实际上是试图读取文件1.txt
应该是在用户的f:\
与语句:
File f11 = new File("f:\\1.txt"); FileInputStream fos = new FileInputStream(f11);
如果find的文件都没问题,但是如果文件没有find,那么程序崩溃,用户发生0错误。 在这种情况下程序员没有做错任何事情。 这可能是一个检查exception,必须抓住程序继续运行。
让我来解释一下RuntimeException
的概念将被清除的第二个场景。 考虑下面的代码:
int a = {1,2,3,4,5}; System.out.println(a[9]);
这是糟糕的编码,会产生ArrayIndexOutOfBoundsException
。 这是RuntimeException
一个例子。 所以程序员不应该真正处理exception,让程序崩溃,然后修改逻辑。
当你想处理它时,你会捕获RuntimeException
。 也许你想重新抛出它作为一个不同的例外,或者将其logging到一个文件或数据库,或者你想在返回types等打开一些例外标志。
当程序执行多个子任务时,您可以捕获RuntimeExceptions(任何语言:意外的exception/“所有”exception),并且完成每一个都可以,而不是停止第一个意外情况。 testing套件是做这件事情的一个很好的情况 – 你想知道哪些testing失败了,而不仅仅是第一次testing。 关键特征是每个testing都独立于所有其他testing – 无论以前的testing是否因为顺序无关而不运行都无关紧要。
另一个常见的情况是服务器; 你不想closures,只是因为一个请求是以你没有预料到的方式变形的。 (除非把状态不一致的可能性降到最低,这真的很重要。)
在这些情况下,要做的事情就是logging/报告exception情况,并继续处理剩余的任务。
人们可以模糊地概括出任何例外:当且仅当在捕捉之后有一些明智的做法是“合适的”捕捉到一个例外: 程序应该如何继续 。
如果客户可以合理预期从exception中恢复,请将其作为检查exception。
如果客户端无法做任何事情来恢复exception,使其成为一个unchecked例外。
这是底线指引。
从Java 文档 。 请阅读这个未经检查的例外 – 争议