在主函数或调用层次结构中的较低层发生致命异常后退出

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");
     }
 }

这种情况应该使用哪种方式?

这对我来说是一个很难的问题,我现在只是分享一些想法。

您需要注意两大因素:

  1. 会致命吗?你能阻止它 destroying/shutting 在程序中吗?
  2. 你能对异常做点什么吗?记录一些有用的信息?通过一些方法恢复它?

第一名

如果它是致命的那么你最好尝试确保程序 exit 优雅地捕获它在适当的层可能就在异常抛出的地方或更高层(这更多地取决于 2 号) ;

第二名

如果您想跟踪一些有用的信息以进行调试,甚至在可能的情况下进行恢复。

那抓不抓到哪里处理就看你的project/system了。

以正常情况为例:

如果需要跟踪调用层的信息,应该在下层捕获异常并抛出异常让calling/higher层拥有:

  1. 要么记录一些有用的调试信息
  2. 或者用其他方法恢复(比如你引入了策略模式,也许你应该尝试其他策略来代替当前的策略来处理同一个作业);

换句话说

不要尝试将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,而不是直接终止程序。