一尘不染

Java无法访问的catch块编译器错误

java

为什么在Java中,Exception即使没有抛出异常,我们也可以捕获它,但是却不能捕获它的子类(“ unchecked”
RuntimeException及其子类除外)。示例代码:

class Test {
    public static void main(String[] args) {
        try {
            // do nothing
        } catch (Exception e) {
            // OK           
        }

        try {
            // do nothing
        } catch (IOException e) {
               // COMPILER ERROR: Unreachable catch block for IOException.
               //This exception is never thrown from the try statement body
        }       
    }
}

有任何想法吗?


阅读 291

收藏
2020-09-08

共1个答案

一尘不染

任何 代码RuntimeException都可以引发A。换句话说,编译器无法轻松预测可以抛出哪种代码。阿可通过捕获块。
__RuntimeException``catch(Exception e)

IOException但是,这是一个检查的异常-
只有声明为抛出该异常的方法调用才可以这样做。编译器可以(合理地)确信除非有声明将其抛出的方法调用,否则它不可能发生。

Java编译器根本不考虑“有没有代码在所有try块内”的局面-它总是让你赶上unchecked异常,在所有 合理的 情况下会出现代码, 可以
潜在地抛出一个未经检查的异常。

从JLS的14.21节开始

如果满足以下两个条件,则可以到达catch块C:

  • try块中的某些表达式或throw语句是可到达的,并且可以引发类型可以分配给catch子句C的参数的异常。
  • 在try语句中没有较早的catch块A,因此C的参数类型与A的参数类型相同或属于其子类。

可以说,编译器应该意识到在您的第一种情况下,try块中 没有 表达式……对我来说,这似乎仍然是一个无法到达的catch子句。

编辑:如注释中所述,第14.20节包含以下内容:

如果catch子句捕获了已检查的异常类型 E1, 但是不存在已检查的异常类型 E2 ,则以下所有条件均成立,这是编译时错误:

  • E2 <: E1
  • try与该catch子句对应的块可以抛出 E2
  • 前面没有catch立即封闭try语句块捕获 E2 或的超 E2

除非 E1 是Exception类。

因此,这似乎是您 实际上 在犯规的内容,但是对于14.21中无法到达的捕获块而言,此规范并不明确。

2020-09-08