Java无法访问的catch块编译器错误
为什么在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 } } }
有任何想法吗?
一个RuntimeException
可能会被任何代码抛出。 换句话说,编译器不能轻易预测哪种代码可以抛出它。 一个RuntimeException
可以被catch(Exception e)
块catch(Exception e)
。
然而, IOException
是一个检查exception – 声明为抛出它的唯一方法调用可以这样做。 编译器可以(合理地)确信它不可能发生,除非有方法调用被声明为抛出它。
Java编译器根本不考虑“在try块内根本没有任何代码”的情况 – 它总是允许你捕获未经检查的exception,因为在所有合理的情况下都会有可能抛出未经检查的exception的代码。
从JLS 第14.21节 :
如果满足以下两个条件,则catch块C是可达的:
- try块中的某些expression式或throw语句是可访问的,并且可以抛出exception,该exception的types可分配给catch子句C的参数。(如果包含它的最内层语句可到达,则expression式被视为可访问)。
- 在try语句中没有早先的catch块A,使得C的参数types与A的参数types相同或是其types的子类。
可以说编译器应该认识到,在你的第一种情况下,在try块中没有任何expression式……看起来对于我来说这仍然是一个不可达的catch子句。
编辑:如注释中所述, 第14.20节包含这一点:
如果
catch
子句捕获检查的exceptiontypesE1,但是不存在检查的exceptiontypesE2 ,则以下所有条件都成立,这是编译时错误:
- E2 <: E1
catch
子句对应的try
块可以抛出E2- 紧接着的try语句的前面的
catch
块没有捕获E2或E2的超types。除非E1是exception类。
所以看起来这就是你实际上所犯的错误,但是规范并不像14.21中的无法达到的抓钩那样清晰。
IOexception只能在编译器预测可能会引发IOExceptionexception的代码中被捕获。 所以你得到一个警告,IOexception永远不会从try语句体中抛出(因为try体内没有任何东西)。
你不能捕获未经检查的exception,因为它们不能被抛出。 您可以捕获Exception
因为未经检查的运行时exception是一个Exception
,可能会被抛出。
因为对于被检查的exception,引发它们的方法必须通过'throws'关键字来明确地陈述这个事实,因此如果一个块在你的情况下没有'抛出IOException',编译器就有了这个信息,被抛出,所以无论你在捕捉之后做什么,都是无法达到的。
IOException
是仅与IO相关的代码抛出的checkedexception。 由于你的try块什么也不做,IO相关的事情都不会发生,IOExceptions永远不会被抛出,所以catch块永远不会被执行,编译器也不会让你绕过它。 正如你所说,exception可能是指任何时候都可能发生的未经检查的运行时exception。 这是未经检查和已检查exception之间的主要区别,这就是为什么编译器不强制执行代码来捕获每个可能的运行时exception。
简单的Java假设任何代码行可以抛出一个通用的Exception
或Throwable
,即。 OutOfMemoryException
,这是一个Error
而不是一个Exception
。 同样适用于NPE。
IOException
是只能由托pipe代码引发的特定exception,所以如果在catch块中没有I / O调用,那么编译器就没有机会去捕获它。
只是为了与C#世界进行比较,在C#中这样的代码将被编译,但是会是一个概念性的错误,因为如果你没有做任何事情,你不会到达catch块。 像ReSharper这样的工具可以提醒你。