从main方法中使用System.exit(num)还是抛出RuntimeException?

25

我有一个单线程应用程序,如果出现问题应该将DOS错误级别设置为非零值。 是抛出RuntimeException还是使用System.exit(nonzero)更好? 我不需要堆栈跟踪,并且我不希望这个应用程序被扩展/重复使用。 这两个选项之间有什么区别?


1
你似乎已经回答了自己的问题。如果你必须设置一个DOS错误代码,你必须使用System.exit(code)。你不能用异常来做到这一点。 - user207421
从主函数抛出RuntimeException会将错误级别设置为3,尽管我不确定为什么或是否在所有情况下都是如此。 - VarV
7个回答

12
除非确实有异常情况,否则请勿抛出异常。System.exit(int)就是为此而存在的。使用它吧。
编辑:我可能误读了你的问题。我认为你在问,当你想要正常退出JVM但信号表明某些东西不太对时,使用抛出异常还是使用System.exit更好。
然而,如果发生的问题已经由Java异常指示,则可以让该异常未经处理地传递。您不必捕获异常并调用System.exit
如果您可以选择自己抛出异常还是调用System.exit,请考虑错误条件是否可能由调用您方法的某些Java代码处理。如果错误直接发生在main方法中,则可能永远不会有调用者来处理该异常,因此您应该调用System.exit。否则,通常最好抛出异常 - 但不是RuntimeException,您应该使用适当表示遇到的错误的异常类型。如有必要,请编写自己的RuntimeException子类。

那么为什么从主函数抛出的异常会设置错误级别呢?它们似乎有某种原因存在。 - VarV
3
当一个应用程序不能成功完成时,它的返回代码应该是非零的。因此,如果有未处理的异常,JVM会自动将返回代码设置为1,这样父进程就知道你的程序是因为出现错误而终止(而不仅仅是因为结束了工作)。 - David Z

7
通常在这种情况下,我会在我的主方法中处理所有的异常,可能通过调用System.exit来处理。这样做可以灵活地处理异常条件,同时仍然满足您以错误代码终止的需求。特别是,它可以让您控制返回代码和任何其他输出,您可能为用户生成(错误消息、堆栈跟踪等)。如果您在主函数中抛出异常(或让异常逃逸),则会失去该控制。
总之,在顶层异常处理程序中才调用System.exit
static public void main() {
   try {
      runMyApp();
   } catch (Exception e) {
      System.exit(1);
   }
}

2
我可能会选择这个解决方案,但我想知道为什么System.exit比从main方法抛出异常更受青睐。 - VarV

4

抛出的异常将打印出堆栈跟踪,如果您不需要它,请使用System.exit。

在退出时,您可以通过System.out向用户发送信息(我假设该应用程序仅在命令行环境中运行)。

您应该考虑捕获所有错误并将错误记录在单独的日志中,这样可以确保当您关闭终端时堆栈跟踪不会永久丢失。为此,请查看log4j,它非常易于使用。


1
是的,它只在命令行环境中运行。我不需要堆栈跟踪,因为它是我们构建过程中的自动化步骤,要么通过要么失败,所以即使是log4j也过于繁琐。 - VarV
那么就采用system.exit的解决方案吧。这是一个很好的解决方案,特别是如果您之后检查返回代码。这样,您可以使用不同的代码来表示出了什么问题,或者只需选择System.exit(-1)。 - Jes

2

APP本身应该使用System.exit。这是它与调用环境(脚本)的接口。任何内部组件当然都应该使用Exception。当你把它们放在一起时,它们可以同时存在:

Application.main(...) {
  parse(args);
  check(...);
  try {
    MyObject o = ...;
    o.doMyStuff();
  } catch (Exception e) {
    System.err.println("Oops, something went wrong!"); // by example, or use a logging framework! // anyway in a shell app System.in/out/err IS my interface with the outworld
    System.exit(ERROR_CODE);
  }
  System.out.println("Worked!");
}

0

这取决于你想向启动程序的脚本报告多少信息。如果脚本旨在执行一系列操作,这可能非常重要。https://shapeshed.com/unix-exit-codes/

示例:我开发了一个Java程序,调用外部API,下载响应并将其保存到文件中。 可能的结果:

  • 0 = OK
  • 5 = HTTP暂时不可用
  • 6 = 无法将文件写入磁盘

现在我的脚本知道出了什么问题,它可以根据结果采取不同的操作。

  • 如果响应= 0,则继续脚本中的下一步
  • 如果响应= 5,则重试(带有延迟)
  • 如果响应= 6,则停止脚本

底线:像任何良好的API一样,清楚地定义您的输入和输出参数,并使用System.exit


-2

System.exit(num)不是一个好的选择,因为它会关闭JVM,而且即使在catch块之后有finally块,它也不会运行。

抛出RuntimeException也可能不是最好的选择,可以像之前提到的那样子类化,这是一个特定于应用程序的异常,我认为这可能是更好的选择。 -Manish


-5

不推荐使用System.exit()。它会关闭JVM。


在这种情况下关闭JVM是可以的,如果出现错误,应用程序就完成了。 - VarV
在我看来,不建议使用通用的RuntimeException。 - Harsha Hulageri
是使用 system.exit(int) 还是 throw new RuntimeException 更好呢?后者是否被认为是通用的 RuntimeException? - VarV
抛出RuntimeException异常比调用System.exit(int)更好。 - Harsha Hulageri
我基本上同意你的观点。我更多地是在寻找“为什么”的部分,但在这种情况下可能没有任何一种方法有优势。我主要担心通过抛出异常设置的错误级别不一致,但通过System.Exit(num)设置的错误级别也不一致,因为它本身也可能会引发异常。 - VarV
我欣赏不同的意见,但请解释清楚。 - Chris

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接