在主函数或调用层次结构中的较低层发生致命异常后退出
Exit after fatal exception in main function or lower in call hierarchy
如果我有一个程序调用的方法在抛出特定异常时必须终止,我是否应该将其设计为将异常传递回 main
以便它可以安全地 return, 或者我应该处理函数中的异常并调用 System.exit(-1)
?
这是我在函数中处理它的意思的示例:
public class MyClass{
public static void main (String[] args){
myFunction(args);
}
public static void myFunction(String[] args){
try{
if(args.length == 0)
throw Exception("Invalid Input");
}catch(Exception e){
System.out.println(e);
System.exit(-1);
}
}
}
这是我所说的传递它的意思的一个例子:
public class MyClass{
public static void main (String[] args){
try{
myFunction(args);
}catch(Exception e){
System.out.println(e);
}
}
public static void myFunction(String[] args) throws Exception{
if(args.length == 0)
throw Exception("Invalid Input");
}
}
这种情况应该使用哪种方式?
这对我来说是一个很难的问题,我现在只是分享一些想法。
您需要注意两大因素:
- 会致命吗?你能阻止它 destroying/shutting 在程序中吗?
- 你能对异常做点什么吗?记录一些有用的信息?通过一些方法恢复它?
第一名
如果它是致命的那么你最好尝试确保程序 exit
优雅地捕获它在适当的层可能就在异常抛出的地方或更高层(这更多地取决于 2 号) ;
第二名
如果您想跟踪一些有用的信息以进行调试,甚至在可能的情况下进行恢复。
那抓不抓到哪里处理就看你的project/system了。
以正常情况为例:
如果需要跟踪调用层的信息,应该在下层捕获异常并抛出异常让calling/higher层拥有:
- 要么记录一些有用的调试信息
- 或者用其他方法恢复(比如你引入了策略模式,也许你应该尝试其他策略来代替当前的策略来处理同一个作业);
换句话说
请不要尝试将exception
引入您的project/system逻辑,exception
应被视为处理意外问题的异常。
很抱歉添加此内容,希望对您有所帮助。
来自this post:
You should catch the exception when you are in the method that knows what to do.
如果抛出异常的方法知道如何处理错误,那么它应该处理它。否则,如果该方法不知道如何处理异常,它应该抛出它。
在你的问题中,当你想在异常发生时退出程序,将异常抛回给 main
方法可能是有意义的。
This post也有一些不错的资料。
几乎没有理由打电话给 System.exit
。也许如果出现某种灾难性情况,您想立即停止 JVM,很难想象会发生什么。所以我想说,没有一些非常具体的要求,永远不要调用 System.exit
。
在main
方法中设置一个try-catch
块,捕获Throwable
,并记录下来。这最大限度地减少了程序中其他地方的异常处理,并鼓励一种快速失败的编程方式,这样异常就不会被吃掉和丢失。
或者,您可能有一个来自 shell 脚本的 Java 小程序 运行。您可以让 main
方法抛出 Exception
并让 shell 脚本调用者重定向 stderr
到一个文件。但是使用真正的记录器可以更好地控制滚动和清除等。
如果您担心可能会抛出一些无法记录的错误(也许我们内存不足并且无法记录而不会导致另一个内存不足错误),请将日志记录添加到调用者中作为预防措施,除了让 Java 程序自己记录日志之外。
这个问题的回答方式表明,从本质上讲,这不是一个主要基于意见的问题。
首先,考虑与此相关的问题“when should you throw an exception"? The correct answer 是 "If, and only if, the alternative would be to fail to establish a post condition or maintain an invariant"。这提醒我们根据方法 post 条件来思考。您提供了一个方法示例解析命令行参数。这应该有一个 post 条件 "the command line arguments are valid"。所以在命令行参数无效的情况下,该规则告诉我们该方法应该抛出异常,并且不需要终止。
其次,考虑为什么会有例外。有些编程语言没有它们(特别是 C)。另一种方法是使用状态代码。异常的优点之一是它们将问题检测(抛出异常)与发生问题时决定做什么(捕获异常)分开。它们为"pushing policy upwards"提供了一种向更高层次调用方法的方法。那么,如果出现问题(例如无效的命令行参数,在您的示例中),程序是否应该终止?那是策略的问题,属于高层次的方法,不属于低层次的方法。同样的论点适用于程序的所有级别:任何方法都不能被证明是终止程序、实施最严厉的策略可能是合理的,因为它可以通过抛出异常来向上推动策略。唯一不能向上推送策略的方法是 main
方法,因为它没有向上推送的调用者。这表明只有 main 方法应该导致程序终止。请注意,JVM 以这种方式运行:即使是根本无法处理且应导致程序终止的虚拟机错误,也会导致抛出 VirtualMachineError
,而不是直接终止程序。
如果我有一个程序调用的方法在抛出特定异常时必须终止,我是否应该将其设计为将异常传递回 main
以便它可以安全地 return, 或者我应该处理函数中的异常并调用 System.exit(-1)
?
这是我在函数中处理它的意思的示例:
public class MyClass{
public static void main (String[] args){
myFunction(args);
}
public static void myFunction(String[] args){
try{
if(args.length == 0)
throw Exception("Invalid Input");
}catch(Exception e){
System.out.println(e);
System.exit(-1);
}
}
}
这是我所说的传递它的意思的一个例子:
public class MyClass{
public static void main (String[] args){
try{
myFunction(args);
}catch(Exception e){
System.out.println(e);
}
}
public static void myFunction(String[] args) throws Exception{
if(args.length == 0)
throw Exception("Invalid Input");
}
}
这种情况应该使用哪种方式?
这对我来说是一个很难的问题,我现在只是分享一些想法。
您需要注意两大因素:
- 会致命吗?你能阻止它 destroying/shutting 在程序中吗?
- 你能对异常做点什么吗?记录一些有用的信息?通过一些方法恢复它?
第一名
如果它是致命的那么你最好尝试确保程序 exit
优雅地捕获它在适当的层可能就在异常抛出的地方或更高层(这更多地取决于 2 号) ;
第二名
如果您想跟踪一些有用的信息以进行调试,甚至在可能的情况下进行恢复。
那抓不抓到哪里处理就看你的project/system了。
以正常情况为例:
如果需要跟踪调用层的信息,应该在下层捕获异常并抛出异常让calling/higher层拥有:
- 要么记录一些有用的调试信息
- 或者用其他方法恢复(比如你引入了策略模式,也许你应该尝试其他策略来代替当前的策略来处理同一个作业);
换句话说
请不要尝试将exception
引入您的project/system逻辑,exception
应被视为处理意外问题的异常。
很抱歉添加此内容,希望对您有所帮助。
来自this post:
You should catch the exception when you are in the method that knows what to do.
如果抛出异常的方法知道如何处理错误,那么它应该处理它。否则,如果该方法不知道如何处理异常,它应该抛出它。
在你的问题中,当你想在异常发生时退出程序,将异常抛回给 main
方法可能是有意义的。
This post也有一些不错的资料。
几乎没有理由打电话给 System.exit
。也许如果出现某种灾难性情况,您想立即停止 JVM,很难想象会发生什么。所以我想说,没有一些非常具体的要求,永远不要调用 System.exit
。
在main
方法中设置一个try-catch
块,捕获Throwable
,并记录下来。这最大限度地减少了程序中其他地方的异常处理,并鼓励一种快速失败的编程方式,这样异常就不会被吃掉和丢失。
或者,您可能有一个来自 shell 脚本的 Java 小程序 运行。您可以让 main
方法抛出 Exception
并让 shell 脚本调用者重定向 stderr
到一个文件。但是使用真正的记录器可以更好地控制滚动和清除等。
如果您担心可能会抛出一些无法记录的错误(也许我们内存不足并且无法记录而不会导致另一个内存不足错误),请将日志记录添加到调用者中作为预防措施,除了让 Java 程序自己记录日志之外。
这个问题的回答方式表明,从本质上讲,这不是一个主要基于意见的问题。
首先,考虑与此相关的问题“when should you throw an exception"? The correct answer 是 "If, and only if, the alternative would be to fail to establish a post condition or maintain an invariant"。这提醒我们根据方法 post 条件来思考。您提供了一个方法示例解析命令行参数。这应该有一个 post 条件 "the command line arguments are valid"。所以在命令行参数无效的情况下,该规则告诉我们该方法应该抛出异常,并且不需要终止。
其次,考虑为什么会有例外。有些编程语言没有它们(特别是 C)。另一种方法是使用状态代码。异常的优点之一是它们将问题检测(抛出异常)与发生问题时决定做什么(捕获异常)分开。它们为"pushing policy upwards"提供了一种向更高层次调用方法的方法。那么,如果出现问题(例如无效的命令行参数,在您的示例中),程序是否应该终止?那是策略的问题,属于高层次的方法,不属于低层次的方法。同样的论点适用于程序的所有级别:任何方法都不能被证明是终止程序、实施最严厉的策略可能是合理的,因为它可以通过抛出异常来向上推动策略。唯一不能向上推送策略的方法是 main
方法,因为它没有向上推送的调用者。这表明只有 main 方法应该导致程序终止。请注意,JVM 以这种方式运行:即使是根本无法处理且应导致程序终止的虚拟机错误,也会导致抛出 VirtualMachineError
,而不是直接终止程序。