【问题标题】:Fatal exception handling in JavaJava中的致命异常处理
【发布时间】:2017-01-26 08:36:01
【问题描述】:

我正在用 Java 创建一个基本的数学解析器,这样做暴露了我对 Java 异常处理的浅薄理解。

当我有这个输入时:

String mathExpression = "(3+5";

我随后致电:

throw new MissingRightParenException();

IDE 强制我用 try/catch 包围,如下所示:

             try {
                    throw new MissingRightParenException();
                } catch (MissingRightParenException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();

                }

但是,为了强制这是一个致命异常,看来我必须添加自己的代码来调用 System.exit(),如下所示:

             try {
                    throw new MissingRightParenException();
                } catch (MissingRightParenException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    System.exit(0);
                }

我不确定我是否理解所有这些背后的语法,尤其是为什么我必须在抛出异常时使用 try/catch 块。

这背后的韵律和原因是什么?

我可以这样做,而不是抛出异常:

new MissingRightParenException();

而不是调用

throw new MissingRightParenException();

所以我想我的问题是 - 如果这是一个致命的异常,那么在为用户提供最佳反馈的同时让它真正致命的最佳方法是什么?

【问题讨论】:

    标签: java


    【解决方案1】:

    如果您想要一个必须捕获的已检查异常 - 但不是立即捕获 - 那么您可以在方法的签名中定义 throws MissingRightParenException

    class MissingRightParenException extends CalculationException {
        ...
    }
    
    class CalculationException extends Exception {
        ...
    }
    
    class MyClass {
    
        int myMathRelatedMethod(String calculation) throws CalculationException {
            ...
            if (somethingWrong) {
                throw new MissingRightParenException("Missing right paren for left paren at location: " + location);
            }
            ...
        }
    
        public static void main(String ... args) {        
            ...
            try {
                myMathRelatedMethod(args[0]);
            } catch (CalculationException e) {
                // stack trace not needed maybe
                System.err.println(e.getMessage());
            }
            ...
        }
    }
    

    您也可以将其定义为RuntimeException原因,但这似乎与您当前的问题不太匹配。

    try {
         ...
         throw new MissingRightParenException();
         ...
    } catch (MissingRightParenException e) {
         // IllegalStateException extends (IS_A) RuntimeException
         throw new IllegalStateException("This should never happen", e);
    }
    

    如果您的 MissingRightParenException 类扩展了 RuntimeException,那么您不必抓住它。该消息将通过所有未显式捕获的方法(或其父类,例如ThrowableExceptionRuntimeException)。 但是,您不应将RuntimeExceptions 用于与输入相关的错误。

    通常用户将获得堆栈跟踪或至少是错误消息,尽管这当然取决于进一步的错误处理。请注意,即使main 也不必处理异常。您只需为 main 方法指定 throws Exception 即可让控制台接收堆栈跟踪。

    所以最后:在方法的签名中使用throws,而不是在要处理它们之前捕获异常。

    【讨论】:

    • PS 在配置我的 IDE 时,我做的第一件事是将 e.printStackTrace() 替换为 // TODO handle exception correctly,然后是 throw new IllegalStateException("Exception not yet correctly handled", e);。您不会“失败”,因此不会弄乱您的控制流程。
    【解决方案2】:

    假设你的异常当前是Exception的子类,是一个Checked Exception,你需要在try catch中处理。如果您可以将您的异常设置为 RunTimeException,则您不再需要执行 try-catch 操作。

    【讨论】:

      【解决方案3】:

      在为用户提供真正致命的同时,最好的方法是什么? 最好的反馈?

      就我个人而言,我不认为缺少括号应该是致命的例外。用户应该可以重试。

      但是,如果您真的想知道,java 无法创建自定义致命异常,因为致命异常意味着系统/jvm 出现问题,而不是程序本身出现问题。不过,您应该将System.exit(0) 更改为System.exit(1) 或不等于0 的任何内容,因为程序以0 作为错误代码退出意味着一切正常,这不是异常的定义。

      我不确定我是否理解所有这些背后的语法

      基本上你在这里做的是抛出一个异常,所以你有两个选择,要么捕获它,要么重新抛出它,但无论如何它必须在某个地方被捕获。然后在catch 中,您只需结束程序返回一个错误代码,这意味着某事失败System.exit(1)

      请参阅此Difference in System. exit(0) , System.exit(-1), System.exit(1 ) in Java 以更好地了解错误代码。

      【讨论】:

        【解决方案4】:

        如果MissingRightParenException 是已检查异常(似乎是这样,否则您的 IDE 不会“唠叨”),那么您必须将其包装在 try ... catch 块中或通过 @987654323 声明它方法定义中的 @ 子句。后者允许您“冒泡”异常并捕获您的方法的调用者抛出 MissingRightParenException 异常。

        您是否考虑过throws 子句?

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-01-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-09-16
          • 1970-01-01
          • 2015-07-22
          相关资源
          最近更新 更多