在最近的一个项目中,我建议在测试工具代码中捕获RuntimeException并记录它。代码处理来自数据库的一系列输入,我不希望测试因任何一个输入失败而停止(Null值,非法参数等)。不用说,我的建议引发了激烈的讨论。
是否可以捕获任何类型的RuntimeException?如果是,那么可以捕获RuntimeExceptions的其他方案是什么?
答案 0 :(得分:87)
您抓住RuntimeException
的原因与捕获任何异常的原因相同:您打算用它做一些事情。也许你可以纠正导致异常的任何事情。也许你只想用不同的异常类型重新抛出。
捕获和忽略任何异常都是非常糟糕的做法。
答案 1 :(得分:31)
除非你能纠正RuntimeException,否则你不想抓住它......
...仅从开发人员的角度来看是真实的......
你必须在他们达到用户界面并让你的用户感到伤心之前抓住所有例外情况。这意味着在“最高级别”,您希望捕捉到进一步发生的任何事情。然后,您可以让用户知道存在问题,同时采取措施通知开发人员,例如发送警报邮件等等......
它基本上被认为是一个无法预测的数据/编程错误,因此您希望改进软件的未来版本,同时让用户亲自操作并以受控方式继续... < / p>
答案 2 :(得分:15)
RuntimeException旨在用于程序员错误。因此,它永远不应该被抓住。有几种情况应该是:
您正在调用来自第三方的代码,在这些代码中,您无法控制何时抛出异常。我认为你应该根据具体情况做这件事,并在你自己的类中包含第三方代码的使用,这样你就可以传回非运行时异常。
您的程序无法崩溃并留下堆栈跟踪供用户查看。在这种情况下,它应该围绕主要和围绕任何线程和事件处理代码。当发生此类异常时,该程序可能会退出。
在您的具体情况下,我将不得不质疑为什么您在测试中出现RuntimeExceptions - 您应该修复它们而不是解决它们。
因此,当您希望程序退出时,您应该保证您的代码只会抛出RuntimeExceptions。只有在想要记录并退出时才应捕获RuntimeExceptions。这与RuntimeExceptions的意图一致。
You can look at this discussion由于人们给出的其他一些原因......我个人在答案中没有找到令人信服的理由。
答案 3 :(得分:7)
多年前,我们编写了一个控制系统框架,Agent对象捕获了运行时异常,如果可以的话继续记录它们。
是的,我们在框架代码中捕获了包含OutOfMemory的运行时异常(并强制使用GC,并且令人惊讶的是,即使运行的代码非常漏洞也是如此。) 我们的代码在做涉及现实世界的非常数学的事情;并且由于微小的舍入错误而不时会出现非数字,并且它也可以应对。
所以在框架/“必须不退出”代码中我认为它是合理的。它工作时非常酷。
代码非常可靠,但它运行的是硬件,硬件往往会给出棘手的答案。
它被设计为在一段时间内无需人为干预。 它在我们的测试中表现得非常好。
作为错误恢复代码的一部分,它可以使用UPS在N分钟内关闭并在M分钟内打开来重新启动整个建筑物。
有时硬件故障需要重启电源:)
如果我记得,电源循环失败后的最后一招是它发送电子邮件给它的所有者,说 “我试图修复自己,我不能;问题出在子系统XYZ”,并包含一个链接,以便向我们发出支持电话。
可悲的是,该项目在能够自我意识之前得到了罐头:)&gt;
答案 4 :(得分:6)
在我的代码中,99%的异常都来自runtime_exception。
我捕获异常的原因是:
答案 5 :(得分:3)
就个人而言,我总是被告知要抓住所有 RuntimeExceptions;但是,您还需要执行关于异常的操作,例如运行故障安全或可能只是通知用户发生了错误。
我工作的最后一个Java项目有一个类似的方法,至少,我们会记录异常,这样如果一个用户打电话抱怨一个bug,我们就可以确切地知道发生了什么,看看错误发生在哪里
编辑1:正如kdgregory所说,捕捉和忽略是两回事,一般来说,人们反对后者: - )
答案 6 :(得分:3)
我们都知道已检查的异常和RuntimeExceptions
是两类异常。总是建议我们处理(try-catch或throw)已检查的异常,因为它们是编程条件,不幸的是程序员不能自己做任何事情;
与FileNotFoundException
一样,如果程序实际上正在尝试读取文件1.txt
,并且应该在f:\
用户的文件中读取File f11 = new File("f:\\1.txt");
FileInputStream fos = new FileInputStream(f11);
,那么程序员就不会将文件放在用户的驱动器上:< / p>
RuntimeException
如果找到该文件就可以了,但是如果找不到该文件,则在另一种情况下会发生的情况是,程序因用户的0错误而崩溃。在这种情况下,程序员没有做错任何事情。这可能是一个已检查的异常,必须捕获该异常,程序才能继续运行。
我还要解释第二种情况,int a = {1,2,3,4,5};
System.out.println(a[9]);
的概念将会明确。请考虑以下代码:
ArrayIndexOutOfBoundsException
这是生成RuntimeException
的糟糕编码。这是{{1}}的一个例子。所以程序员实际上不应该处理异常,让它崩溃程序,然后修复逻辑。
答案 7 :(得分:2)
当您想要处理它时,您会抓住RuntimeException
。也许您想将它重新抛出为不同的异常或将其记录到文件或数据库,或者您想在返回类型中打开一些异常标志等。
答案 8 :(得分:1)
当程序执行多个子任务时,您会捕获RuntimeExceptions(使用任何语言:意外异常/“所有”异常),并且有意义地完成每个子任务,而不是在第一个意外情况下停止。测试套件是一个很好的情况 - 你想知道哪些所有测试失败,而不仅仅是第一次测试。关键特征是每个测试都独立于所有其他测试 - 无论先前的测试是否因为顺序不重要而无法运行也无关紧要。
另一种常见情况是服务器;你不想因为一个请求以你没想到的方式出错而关闭。 (除非真的,最重要的是尽量减少状态不一致的可能性。)
在任何这些情况下,适当的做法是记录/报告异常并继续执行剩余的任务。
人们可以模糊地概括为任何异常:只有当在 之后 / em>的
答案 9 :(得分:0)
如果可以合理地期望客户端从异常中恢复,请将其作为检查异常。
如果客户端无法执行任何操作以从异常中恢复,请将其设置为未经检查的异常。
这是底线指南。
来自Java Docs。请阅读此Unchecked Exceptions — The Controversy