try {
throw new FileNotFoundException();
} catch (IOException e) {
e.printStackTrace();
}
catch (Exception e) {
e.printStackTrace();
}
有人能告诉我为什么编译器不会将第二个catch块视为无法访问的代码吗?但在以下情况中:
try {
throw new FileNotFoundException();
} catch (Exception e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
第二个拦截块被认为无法到达?
毕竟,FileNotFoundException属于IOException,就像Exception一样 .
Edit 请澄清:编译器将知道基于方法的方法抛出异常's throws clause. But it may not necessarily know the specific type of exception (under that class of exception). So if a method throws exception ' A ', compiler won'知道实际异常是'A'还是'A'的子类型,因为这只是在运行时确定的 . 然而,编译器将知道永远不会抛出'X'类型的异常,因此为X提供catch块是错误的 . 这是正确的吗?
3 回答
编译器不能假设从
try
块抛出的唯一可能异常将是FileNotFoundException
. 那个's why it doesn't认为你的第一个代码示例中无法访问第二个catch
块 .如果出于某种未知原因,在创建
FileNotFoundException
实例时(完全可能)抛出RuntimeException
会怎么样?然后怎样呢?在您的第一个代码示例中,第二个
catch
块将捕获该意外的运行时异常,而第一个块将在它被抛出时处理FileNotFoundException
.但是,在第二个代码示例中,任何和所有异常都会被第一个
catch
块捕获,从而使第二个块无法访问 .EDIT:
为了更好地理解为什么第一个代码中的
catch(Exception e)
块不被编译器视为无法访问,请尝试以下代码,并注意第二个catch
如何可以访问:输出:
First case:
如你所见,首先是
IOException
. 这意味着我们的目标只是 one 特定的例外 . 然后在第二次捕获中,我们的目标是IOException
以外的任何其他异常 . 因此它的逻辑性 .In second:
我们在第一个块中捕获了 any 异常(无论是
IOException
还是其他一些异常) . 因此,将不会到达第二个块,因为所有内容都已包含在第一个块中 .换句话说,在第一种情况下,我们的目标是某些特定的例外,而不是任何其他例外 . 在第二种情况下,我们首先针对所有/任何异常,而不是针对特定异常 . 由于我们已经处理了所有异常,因此稍后具有特定异常将不具有任何逻辑意义 .
TL; DR
编译器认为
FileNotFoundException()
可能不是唯一抛出的Exception
.解释
JLS§11.2.3 Exception Checking
这意味着如果编译器认为catch块可能抛出的唯一异常是
FileNotFoundException()
,它会警告您第二个catch块 . 这不是这种情况 .但是,以下代码
发生这种情况是因为编译器评估try块以确定可能抛出哪些异常 .
由于编译器没有在
Èxception e
上警告我们,它认为可能抛出其他异常(例如RunTimeException) . 由于处理这些RunTimeExceptions不是编译器的工作,它让它滑倒 .其余的答案是阅读以了解异常捕获背后的机制 .
架构
正如您所看到的,
Exception
在层次结构中很高,因此必须在层次结构中较低的IOException
之后最后声明 .示例
想象一下,抛出一个
IOException
. 由于它是从Exception
继承而来的,我们可以说IOException IS-A Exception因此,它总是会被捕获在Exception
块中,并且IOException
块将无法访问 .真人生活的例子
比方说,你在商店,必须选择裤子 . 卖家告诉你,你必须尝试从最大的裤子到最小的裤子,如果你找到一个你可以穿的(即使它不是你的尺寸),你必须采取它 .
你会发现自己买的裤子太大而且你的尺码太大,你也没有机会找到适合自己的裤子 .
你去另一家商店:那里,你正好相反 . 您可以选择从最小到最大的裤子,如果您找到可以穿的裤子,您必须服用 .
你会发现自己在买裤子确切的大小 .
这有点类比,有点奇怪,但它说明了一切 .
自Java 7:multi-catch
从Java 7开始,您可以选择将try块中可能抛出的所有类型的异常包含在一个且只有catch块中 .
警告:您还必须尊重层次结构,但这次是从左到右 .
在你的情况下,它会