Java 在主函数或调用层次结构中的较低级别出现致命异常后退出

Java 在主函数或调用层次结构中的较低级别出现致命异常后退出,java,exception-handling,Java,Exception Handling,如果我有一个调用某个方法的程序,该方法在抛出特定异常时必须终止,那么我应该将其设计为将异常传递回main,以便它可以安全返回,还是应该在函数中处理异常并调用System.exit(-1) 下面是我在函数中处理它的一个示例: public class MyClass{ public static void main (String[] args){ myFunction(args); } public static void myFunction(St

如果我有一个调用某个方法的程序,该方法在抛出特定异常时必须终止,那么我应该将其设计为将异常传递回
main
,以便它可以安全返回,还是应该在函数中处理异常并调用
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");
     }
 }

在这种情况下应该使用哪种方法?

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

您需要注意两个主要因素:

  • 是致命的吗?你能阻止它破坏/关闭程序吗
  • 你能处理一下例外情况吗?记录一些有用的信息?通过一些方法恢复它
  • 第一 如果它是致命的,那么您最好尝试确保程序
    优雅地退出
    ,方法是在适当的层中捕获它,可能就在异常抛出的地方或更高的层(这更多地取决于第2层)

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

    然后,您是否捕获它并在何处处理它取决于您的项目/系统

    以正常情况为例:

    如果您需要跟踪调用层中的信息,您应该在较低层捕获异常并抛出异常,以便让调用层/较高层拥有它:

  • 或者记录一些有用的调试信息
  • 或者通过其他方法恢复它(比如你引入了策略patten,也许你应该尝试其他策略来代替当前的策略来处理相同的任务) 另一个词 请不要尝试在项目/系统逻辑中引入异常,
    异常应被视为处理意外问题的异常

    很抱歉添加此内容,希望对您有所帮助

    来自:

    当您使用知道该做什么的方法时,应该捕获异常

    如果抛出异常的方法知道如何处理错误,那么它应该处理错误。否则,如果该方法不知道如何处理异常,它应该抛出它

    在您的问题中,由于您希望在异常发生时退出程序,因此可能有必要将异常抛出回
    main
    方法


    还有一些很好的信息。

    没有什么理由调用
    系统。退出
    。也许如果出现了一些灾难性的情况,您希望立即停止JVM,那么很难想象会是什么情况。所以我想说,如果没有一些非常具体的要求,永远不要调用
    System.exit

    main
    方法中设置
    try catch
    块,catch
    Throwable
    ,并记录它。这可以最大限度地减少程序中其他地方的异常处理,并鼓励采用一种快速失败的编程方式,这样异常就不会被吃掉和丢失

    或者,您可以使用shell脚本运行一个小型Java程序。您可以让
    main
    方法抛出
    Exception
    ,并让shell脚本调用程序将
    stderr
    重定向到一个文件。但使用真正的记录器可以更好地控制滚动和吹扫等操作


    如果您担心会抛出一些无法记录的错误(可能是内存不足,无法记录而不会导致另一个内存不足错误),那么作为预防措施,除了让Java程序自己记录之外,还要将日志添加到调用方

    这个问题的回答方式可以从本质上表明,它不是一个主要基于观点的问题

    首先,考虑相关的问题“?”对此的解释是“如果且仅当替代方案将无法建立后置条件或保持不变”。这提醒我们从方法后条件的角度来思考。您提供了一个解析命令行参数的方法示例。应该有一个post条件“命令行参数有效”。因此,在命令行参数无效的情况下,该规则告诉我们该方法应该抛出异常,而不需要终止


    第二,考虑为什么会有例外。有些编程语言没有它们(特别是C)。另一种方法是使用状态代码。异常的优点之一是,它们将问题的检测(抛出异常的地方)与在出现问题时(捕获异常的地方)决定要做什么分开。它们提供了一种将策略“向上推”到更高级别调用方法的方法。因此,如果出现问题(例如,在您的示例中,命令行参数无效),程序是否应该终止?这是一个政策问题,因此属于更高层次的方法,而不是低层次的方法。同样的观点也适用于整个程序的所有级别:没有任何方法可以被证明是终止程序,执行尽可能激烈的策略,因为它可以通过抛出异常将策略向上推。唯一无法向上推送策略的方法是
    main
    方法,因为它没有要向上推送的调用方。这表明只有main方法才能导致程序终止。请注意,JVM以这种方式运行:即使是根本无法处理的虚拟机错误,也会导致程序终止,导致抛出
    VirtualMachineError
    ,而不是直接终止程序

    如果您只是让异常从
    main()
    未捕获地抛出,程序将终止。如果异常是致命的,为什么要捕获它?另外,
    catch(Exception e){System.exit(-1);}
    通常不是一个好主意。它是一个由于无效输入而引发的异常,这不是一个好主意