我希望抛出exception时退出程序的最佳方法是什么?
我正在编写一个读取文件的Java程序。 该程序至关重要地依赖于此文件,所以我真的希望程序在读取文件时因任何原因而导致IOException。
结束该计划的最佳方式是什么? 我想我被迫在try / catch块中包围我的文件读取,所以我应该在catch中添加一个System.exit(0)
吗? 例如,我应该做以下的事情吗?
try { BufferedReader br = new BufferedReader(new FileReader("myfile.txt")); String line; while ((line = br.readLine()) != null) { // process... } } catch(IOException e) { System.out.println("Error: " + e); System.exit(0); // ??? }
如果让exception一直传播到main()
方法,程序将结束。 没有必要调用System.exit
,只是允许exception自然地将堆栈冒泡(通过添加throws IOException
)到必要的方法。
编辑:正如@Brian指出的那样,您可能希望在main
方法中捕获IOException
,并在那里调用System.exit
,提供人类可读的错误消息(堆栈跟踪可能会吓到人)。 另外,正如@MeBigFatGuy所说,从代码堆栈中调用System.exit
是不好的做法,并限制了代码的可重用性。 如果必须使用System.exit
,则将其保留在main
方法的main
。
没关系。 但是0
作为退出代码意味着程序按预期结束。 你会想要使用不同的数字;)
如果你真的希望立即终止该程序,而不是让程序的上层决定做什么(可能会在某天延长你的程序核心以允许从各种网站选择myfile.txt
的来源,或者演讲- 文本合成,或直接脑转移),你应该调用: System.exit(1)
(或其他一些非零退出状态)。
退出代码为0
表示执行正常完成的shell(和父进程)。 非零退出代码报告存在错误。 这对于制作出色的工具来通知管理员exception执行错误或编写友好的小程序至关重要:
./fiddle_with_words myfile.txt || mail -s "program failed" grautur@example.com
@gratur在@skaffman的回答中发表评论。
因此,如果我理解正确,我通过删除try / catch块并向该方法添加“throws IOException”(以及调用该方法的方法等)来让exception冒泡? 我觉得有点蠢,因为现在我必须添加一堆“抛出IOException”到处 – 我的ickiness被误导了?
我认为这取决于。 如果exception只需要冒出少量级别,并且传播IOException
的方法是有意义的,那么这就是你应该做的。 关于允许exception传播没有什么特别“icky”。
另一方面,如果IOException
必须传播到多个级别,并且没有可能在特定点之外专门处理它,您可能希望:
- 定义一个自定义
ApplicationErrorException
,它是RuntimeException
的子类, - 捕获其源附近的
IOException
并在其位置抛出ApplicationErrorException
…当然,cause
设置为 - 在
main
方法中捕获ApplicationErrorException
exception。
在您捕获ApplicationErrorException
main
中,您可以使用非零状态代码调用System.exit()
,并可选择打印或记录堆栈跟踪。 (实际上,您可能希望通过专门化“应用程序错误”exception来区分您执行和不希望堆栈跟踪的情况。)
请注意,我们仍然允许exception传播到main
…出于@ skaffman的答案中解释的原因。
使这个问题复杂化的最后一件事是在main
线程之外的某些线程的堆栈上抛出的exception。 您可能不希望exception被处理并转换为另一个线程堆栈上的 System.exit()
…因为这不会让其他线程有机会干净地关闭。 另一方面,如果您不执行任何操作,则默认行为是另一个线程以未捕获的exception终止。 如果没有什么是join()
线程,这可以被忽视。 不幸的是,没有简单的“一刀切”的解决方案。