我有一个单线程应用程序,如果出现问题,应该将 DOS 错误级别设置为非零值。是抛出 RuntimeException 还是使用 System.exit(nonzero) 更好?我不需要堆栈跟踪,也不希望这个应用程序被扩展/重用。这两个选项有什么区别?
7 回答
除非您确实有异常情况,否则不要抛出异常。System.exit(int)
正是因为这个原因。用它。
编辑:我想我可能误读了你的问题。我以为你在问,当你想正常退出 JVM 但发出信号表明事情不太对劲时,是抛出异常还是使用System.exit
.
但是,如果发生的问题已经由 Java 异常指示,则可以不处理该异常。您不必捕获异常并调用System.exit
.
如果您可以选择是自己抛出异常还是调用异常,请System.exit
考虑错误条件是否可能由调用您的方法的某些 Java 代码处理。如果错误直接发生在main
方法中,那么可能永远不会有调用者来处理异常,因此您可能应该调用System.exit
. 否则,通常最好抛出异常 - 但不是RuntimeException
,您可能应该使用适当表示您遇到的错误的异常类型。RuntimeException
如有必要,编写您自己的子类。
通常在这种情况下,我会在我的 main 方法中处理所有异常,可能通过调用System.exit
. 这使您可以灵活地选择在哪里/是否/如何处理异常情况,同时仍然满足您以错误代码终止的需要。特别是,它使您可以控制返回代码和您可能为用户生成的任何其他输出(错误消息、堆栈跟踪等)。如果您在 main 中抛出异常(或让异常逃逸),您将失去该控制。
总而言之,System.exit
仅在您的顶级异常处理程序中调用:
static public void main() {
try {
runMyApp();
} catch (Exception e) {
System.exit(1);
}
}
抛出的异常将打印出堆栈跟踪,如果您不需要,您应该使用 System.exit。
退出时,您可以通过 Sytem.out 通知用户(我假设该应用程序仅在命令行环境中运行)。
您应该考虑只捕获所有错误并将错误记录在单独的日志中,这样可以确保在您关闭终端时堆栈跟踪不会永远丢失。为此目的看一下 log4j,它真的很容易使用。
APP 本身应该使用 System.exit。它是它与调用环境(脚本)的接口。当然,任何内部组件都应该使用异常。当你把它放在一起时,它可以是两个人:
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!");
}
这取决于您要向启动程序的脚本报告多少信息。如果脚本旨在执行一系列操作,这可能非常重要。https://shapeshed.com/unix-exit-codes/
示例:我开发了一个调用外部 API、下载响应并将其保存到文件的 Java 程序。可能的结果:
- 0 = 正常
- 5 = HTTP 暂时不可用
- 6 = 无法将文件写入磁盘
现在我的脚本知道出了什么问题,它可以根据结果采取不同的行动。
- 如果 response = 0,继续脚本中的下一步
- 如果响应 = 5,重试(有延迟)
- 如果 response = 6,停止脚本
底线:像任何好的 api 一样,清楚地定义您的输入和输出参数并使用System.exit
.
System.exit(num) 不是一个好的选择,因为它关闭了 JVM,而且如果你有 after catch 块,它甚至没有运行 finally 块。
抛出 RuntimeException 也可能不是最好的选择,可以像前面提到的那样子类化,这是应用程序特定的异常,在我看来可能是一个更好的选择。-马尼什
不推荐 System.exit()。它关闭 JVM。