在最近的项目中,我建议在测试工具代码中捕获RuntimeException并将其记录下来。该代码处理来自数据库的一系列输入,并且我不希望由于任何一个输入(空值,非法参数等)失败而导致测试停止。不用说,我的建议引起了热烈的讨论。
捕获任何一种RuntimeException是否可以接受?如果是,那么可以捕获RuntimeExceptions的其他方案还有哪些?
Answers:
捕获RuntimeException
此异常的原因与捕获任何异常的原因相同:您打算对其进行处理。也许您可以纠正导致异常的任何原因。也许您只是想重新抛出其他异常类型。
但是,捕获和忽略任何异常是非常糟糕的做法。
RuntimeException旨在用于程序员错误。因此,它永远不会被抓住。在某些情况下应为:
您正在调用来自第三方的代码,您无法控制他们何时抛出异常。我认为您应该根据具体情况进行此操作,并将第三方代码的用法包装在您自己的类中,以便可以传回非运行时异常。
您的程序无法崩溃,并且不会留下堆栈跟踪供用户查看。在这种情况下,它应该围绕main以及所有线程和事件处理代码。当此类异常发生时,程序可能也应该退出。
在您的特定情况下,我将不得不质疑为什么在测试中出现RuntimeExceptions-您应该修复它们而不是解决它们。
因此,您应该保证您的代码仅在想要退出程序时才抛出RuntimeExceptions。您只应在想记录RuntimeExceptions并退出时才捕获它。这符合RuntimeExceptions的意图。
几年前,我们编写了一个控制系统框架,Agent对象捕获了运行时异常,并在可能的情况下将其记录下来并继续。
是的,我们在框架代码中捕获了包括OutOfMemory在内的运行时异常(并强制执行了GC,这令人惊讶的是,即使泄漏非常严重的代码也能正常运行)。由于小数舍入错误,有时会出现Not-A-Number的问题,因此也可以解决。
因此,在框架/“不得退出”代码中,我认为这是合理的。当它起作用时,它非常酷。
该代码相当可靠,但是它运行硬件,并且硬件有时会给出一些棘手的答案。
它设计为一次可以运行几个月,而无需人工干预。在我们的测试中,它表现得非常出色。
作为错误恢复代码的一部分,它可以使用UPS在N分钟内关闭并在M分钟内打开的能力来重启整个建筑物。
有时,硬件故障需要重新上电:)
如果我还记得的话,在电源重启失败后的最后一招就是向其所有者发送电子邮件,说“我试图修复自己,但我不能解决;问题出在XYZ子系统上”,并包括一个提出支持的链接打电话给我们。
可悲的是,该项目在变得自我意识之前就被罐装了:)>
我们都知道检查异常和RuntimeExceptions
是异常的两类。始终建议我们处理(尝试捕获或抛出)已检查的异常,因为不幸的是它们是编程条件,程序员不能单独执行任何操作。就像FileNotFoundException
不是程序员将文件放置在用户驱动器上,如果程序实际上试图读取该文件1.txt
,该文件应该f:\
带有以下语句:
File f11 = new File("f:\\1.txt");
FileInputStream fos = new FileInputStream(f11);
如果找到该文件就可以了,但是在另一种情况下如果找不到该文件又会发生什么,则程序将崩溃,并出现用户0错误。在这种情况下,程序员没有做错任何事情。这可能是一个已检查的异常,必须捕获该异常才能使程序继续运行。
让我也解释一下第二种情况,在这种情况下概念RuntimeException
将很清楚。考虑以下代码:
int a = {1,2,3,4,5};
System.out.println(a[9]);
这是不良的编码,会产生ArrayIndexOutOfBoundsException
。这是一个示例RuntimeException
。因此,程序员不应实际处理该异常,不要让该异常使程序崩溃,然后再修复逻辑。
当程序执行多个子任务时,您会捕获RuntimeExceptions(以任何语言:意外的异常/“所有”异常),并且有可能完成每个任务,而不是在出现第一个意外情况时停止,这很有意义。测试套件是执行此操作的好方法-您想知道所有测试中哪些失败了,而不仅仅是第一个测试。关键特征是每个测试都独立于其他所有测试-先前的测试是否不重要并不重要,因为顺序并不重要。
另一个常见的情况是服务器。您不希望仅因为一个请求的格式不符合您的预期而关闭。(除非最小,非常重要的是最小化状态不一致的可能性。)
在任何这些情况下,适当的操作是记录/报告异常并继续执行剩余的任务。
一个模糊的概括可以归结为任何异常:只有在捕获后有明智的事情要做的情况下,“适当地捕获”异常:程序应如何继续。
如果可以合理地期望客户端从异常中恢复,请使其成为已检查的异常。
如果客户端无法采取任何措施来从异常中恢复,请将其设置为未经检查的异常。
这是底线准则。
来自Java Docs。请阅读以下未经检查的例外情况-争议