我希望抛出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方法中捕获ApplicationErrorExceptionexception。

在您捕获ApplicationErrorException main中,您可以使用非零状态代码调用System.exit() ,并可选择打印或记录堆栈跟踪。 (实际上,您可能希望通过专门化“应用程序错误”exception来区分您执行和不希望堆栈跟踪的情况。)

请注意,我们仍然允许exception传播到main …出于@ skaffman的答案中解释的原因。


使这个问题复杂化的最后一件事是在main线程之外的某些线程的堆栈上抛出的exception。 您可能不希望exception被处理并转换为另一个线程堆栈上的 System.exit() …因为这不会让其他线程有机会干净地关闭。 另一方面,如果您不执行任何操作,则默认行为是另一个线程以未捕获的exception终止。 如果没有什么是join()线程,这可以被忽视。 不幸的是,没有简单的“一刀切”的解决方案。