为什么在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
}
}
}
Run Code Online (Sandbox Code Playgroud)
有任何想法吗?
Jon*_*eet 25
任何代码RuntimeException都可以抛出A. 换句话说,编译器无法轻易预测可以抛出哪种代码.A 可以被一个块抓住.RuntimeExceptioncatch(Exception e)
IOException但是,是一个经过检查的异常 - 只有声明抛出它的方法调用才能这样做.除非有声明抛出它的方法调用,否则编译器可以(合理地)确信它不可能发生.
Java编译器根本不考虑"有一个在所有的try块中无码"的情况-它总是让你赶上unchecked异常,在所有合理的情况下会出现代码,可以潜在地抛出一个未经检查的异常.
从JLS 第14.21节:
如果满足以下两个条件,则可以访问catch块C:
- try块中的某些表达式或throw语句是可以访问的,并且可以抛出一个异常,其类型可以赋予catch子句C的参数.(如果包含它的最内层语句可以访问,则表达式被认为是可到达的.)
- try语句中没有先前的catch块,因此C的参数类型与A参数类型的子类相同.
可以说编译器应该意识到在你的第一种情况下try块中没有表达式......看起来这对我来说仍然是一个无法访问的catch子句.
编辑:如评论中所述,第14.20节包含:
如果
catch子句捕获已检查的异常类型E1,但是没有检查的异常类型E2,以便以下所有内容成立,则为编译时错误:
- E2 <:E1
try对应于该catch子句的块可以抛出E2- 前面没有
catch立即封闭try语句块捕获E2或的超E2.除非E1是类Exception.
所以看起来这就是你实际上在犯规的情况,但规格并不像14.21中无法到达的陷阱那么清晰.
只有在编译器预测代码中可能存在抛出IOException的内容时,才能捕获IO异常.因此,您将收到一条警告,即IO异常永远不会从try语句体中抛出(因为try的正文中没有任何内容).
| 归档时间: |
|
| 查看次数: |
36683 次 |
| 最近记录: |