Java中的致命异常处理

Java中的致命异常处理,java,Java,我正在用Java创建一个基本的数学解析器,这样做暴露了我对Java异常处理的肤浅理解 当我有此输入时: String mathExpression = "(3+5"; 我随后呼吁: throw new MissingRightParenException(); IDE迫使我围绕着一个try/catch,如下所示: try { throw new MissingRightParenException();

我正在用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();

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

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

什么是最好的方法,让它真正致命,同时给用户 最佳反馈

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

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

我不确定我是否理解这一切背后的语法

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

有关错误代码的更好理解,请参阅此部分。

如果您希望获得必须捕获的已检查异常(但不是立即捕获),则可以在方法的签名中定义
抛出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());
        }
        ...
    }
}
您还可以将其定义为运行时异常的原因,但这似乎与您当前的问题不匹配

try {
     ...
     throw new MissingRightParenException();
     ...
} catch (MissingRightParenException e) {
     // IllegalStateException extends (IS_A) RuntimeException
     throw new IllegalStateException("This should never happen", e);
}
如果您的
MissingRightParenException
类扩展了
RuntimeException
,那么您不必捕获它。消息将通过所有未显式捕获的方法(或其父类,如
Throwable
Exception
RuntimeException
)传递。但是,对于与输入相关的错误,不应使用
RuntimeException
s

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


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

如果
MissingRightParenException
是一个选中的异常(似乎是这样,否则IDE不会“唠叨”),那么要么你必须将其包装在
中,然后尝试。。。catch
通过方法定义中的
throws
子句阻止或声明它。后者允许您“冒泡”异常,并捕获抛出
MissingRightParenException
异常的方法的调用方


您是否考虑过一个
throws
子句?

PS配置IDE时,我做的第一件事是将
e.printStackTrace()
替换为
//正确处理异常
,然后是
抛出新的非法状态异常(“异常尚未正确处理”,e)。您不会“失败”,因此不会扰乱您的控制流。