捕获未在本地抛出的异常?

时间:2014-05-22 21:31:23

标签: java exception

我的问题与try catch块的语法行为有关

使用catch来清空try块

void fun() {
    try {}
    catch(Exception e) {}
}

try {}
catch(ArrayIndexOutOfBoundsException e) {}

编译好但编译器抱怨

try {}
catch(IOException e) {}

为什么编译器允许捕获任何类型为Exception或RuntimeException的东西,而它却抱怨带有已检查异常的无法访问的代码?是因为JVM代码可以抛出这些类型吗? JVM怎么可能在空的try块中抛出ArrayIndexOutOfBoundsException?

1 个答案:

答案 0 :(得分:10)

空块是一种特殊情况,不是由JLS专门处理的。 JLS 所需要的需要的是,如果捕获到已检查的异常,try块中的代码必须能够抛出该异常(即,它直接抛出或称为声明可能抛出它的方法。)

换句话说,有一个专门针对已检查异常的健全性检查,但不会针对所有异常进行检查,并且需要额外考虑已检查的异常。

JLS 14.21中对此进行了描述,具体为:

  

如果由于无法访问语句而无法执行该语句,则为编译时错误。

     

...

     

如果满足以下两个条件,则可以访问catch块C

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

         

    表达式的正常和突然完成见§15.6。

  •   
  • try语句中没有先前的catch块A,因此C的参数类型与A类型的子类相同的参数。

  •   

强调添加:它表明如果您捕获未经检查的异常类型,则可以访问catch块。

我个人认为措辞有点令人困惑。稍微重写一下,第一个要点就是说catch子句必须抓住其中一个:

  • 未经检查的例外
  • Exception
  • Throwable(除了Exception之外,Object除了try之外唯一的超类,你无法抓住它们。
  • catch块可以抛出的已检查异常

由于catch中之前的try,第二个子弹防范try { whatever(); } catch (Exception e) { handleException(e); } catch (NullPointerException e) { // This block is unreachable, because a NullPointerException is an // Exception and will thus be handled by the previous catch block. handleNpe(e); } 阻止无法访问。例如:

{{1}}