编译器如何识别java中从不从try语句体抛出异常

编译器如何识别java中从不从try语句体抛出异常,java,exception,Java,Exception,当我捕获一个ParseException(代码1)时,编译器会大叫“ParseException的不可访问的捕获块。这个异常永远不会从try语句体中抛出。”。但当我捕捉到一个异常(代码2)时,它是一个哑巴。为什么会这样 代码1: try { int i = 0; }catch (ParseException e1) { //Unreachable catch block for ParseException. This exception is never thrown from the

当我捕获一个
ParseException
(代码1)时,编译器会大叫“
ParseException的不可访问的捕获块。这个异常永远不会从try语句体中抛出。”。但当我捕捉到一个
异常
(代码2)时,它是一个哑巴。为什么会这样

代码1:

try {
    int i = 0;
}catch (ParseException e1) { //Unreachable catch block for ParseException. This exception is never thrown from the try statement body
    e1.printStackTrace();   
}
代码2:

try {
    int i = 0;
}catch (Exception e2) { // ............. (dumbed???)
    e2.printStackTrace();   
}

注意:我不小心在其他地方注意到了这一点。上面的一个只是一个模拟例子。

原因很简单。分配整数可能导致StackOverflowException,或者当前线程可能被中断(导致InterruptedException)。两者都是Exception的子类,因此可能会被捕获

另一方面,ParseException是一个已检查的异常,您的代码不能抛出它。因此,无法到达的捕捉块


编译器只是为
捕获强制执行JLS可达性规则;看

当以下两项均为真时,可到达捕捉块C:

  • C参数的类型可能是未检查的异常类型或异常或异常的超类,或者try块中的某个表达式或throw语句是可访问的,并且可以抛出类型可分配给C参数类型的已检查异常。(如果包含表达式的最内层语句是可访问的,则表达式是可访问的。)

    有关表达式的正常和突然完成,请参见§15.6

  • try语句中没有较早的catch块A,因此C的参数类型与A的参数类型相同或是A的参数类型的子类

  • 如您所见,假定未检查异常的捕获是可访问的,但只有当
    try
    块直接抛出或调用抛出该异常的方法时,才能访问已检查异常的捕获



    未检查异常规则的基本原理是,很难指定未检查异常可能发生或不发生的情况。(事实上,这取决于JVM实现,除其他外,因此您可能会争辩说,不可能比“未经检查的异常可能在任何地方发生”更严格地指定任何异常……这就是当前的可达性规则松散地暗示的。)

    我猜这与事实有关,
    ParseException
    是一个已检查的异常,而
    exception
    包括已检查和未检查的异常啊!那个骗子!忘了。谢谢你!实际上,分配
    i
    变量不会在该点导致堆栈溢出。堆栈帧在条目上分配给封闭方法。好的,在这一点上不可能出现异常或错误(可能除了
    ThreadDeath
    …)。为了真正的原因,请阅读我的答案。