为什么在 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
}
}
}
有什么想法吗?
7条答案
按热度按时间zkure5ic1#
因为对于检查过的异常,抛出它们的方法必须通过'throws'关键字显式地声明这个事实,因此,如果一个块在您的情况下没有'throws ioexception',编译器就有信息表明ioexception不可能被抛出,所以无论您在捕获之后做什么,它都是不可到达的。
y3bcpkx12#
如果我们从上面每个人的评论中总结一下,就可以得出这样的结论:像ioexception及其子类这样的完全检查过的异常是由编译器严格检查的,并由相关的catch子句抛出。但是对于runtimeexception和exception或throwable(这两个都是部分检查的exception,因为它们的runtimeexception是子/孙)编译器不能在编译时说并允许它通过。
所以。。
但是
omqzjyyz3#
您不能捕获取消thrown检查的异常,因为它们不能被抛出。你可以抓住
Exception
因为未检查的运行时异常是Exception
可能会被抛出。qvsjd97n4#
只有当编译器预测代码中可能存在引发ioexception的内容时,才可以捕获io异常。因此,您将收到一个警告:决不会从try语句体抛出io异常(因为try语句体中没有任何内容)。
cnh2zyt35#
IOException
是仅由io相关代码引发的选中异常。因为try块什么都不做,所以不会发生任何与io相关的事情,也不会抛出ioexceptions,所以catch块不可能被执行,编译器也不会让你处理它。正如您所说,异常可能是指在任何时刻都可能发生的未经检查的运行时异常。这就是未检查异常和已检查异常之间的主要区别,这就是为什么编译器不强制执行代码来捕获所有可能的运行时异常。egdjgwm86#
简单地说,java假设任何代码行都可以抛出一个泛型
Exception
或者Throwable
,即。OutOfMemoryException
这是一个Error
相当于Exception
. npe也是如此。IOException
是一个只能由托管代码引发的特定异常,因此如果catch块中没有i/o调用,编译器就没有机会捕捉它。与c#world相比,在c#中,这样的代码将被编译,但这将是一个概念上的错误,因为如果不执行任何操作,就不会到达catch块。诸如resharper之类的工具可以警告您这一点。
dzjeubhm7#
一
RuntimeException
可能被任何代码抛出。换句话说,编译器不能很容易地预测什么样的代码可以抛出它。一RuntimeException
会被一个catch(Exception e)
阻止。IOException
但是,是一个选中的异常-只有声明为抛出它的方法调用才能这样做。编译器可以(合理地)确信它不可能发生,除非有声明抛出它的方法调用。java编译器根本不考虑“try块中根本没有代码”的情况—它总是允许您捕获未检查的异常,因为在所有合理的场景中,都会有可能抛出未检查异常的代码。
根据jls第14.21节:
如果以下两个条件都为真,则可以到达catch块c:
try块中的某个表达式或throw语句是可访问的,并且可以抛出类型可分配给catch子句c的参数的异常(如果包含表达式的最内层语句是可访问的,则认为表达式是可访问的。)
try语句中没有较早的catch块a,因此c的参数类型与a的参数类型相同或是a的参数类型的子类。
可以说,编译器应该意识到,在第一种情况下,try块中没有表达式。。。在我看来,这仍然是一个无法达到的条款。
编辑:如评论所述,第14.20节包含以下内容:
如果
catch
子句捕获选中的异常类型e1,但不存在选中的异常类型e2,因此以下所有类型均有效:e2<:e1
这个
try
块对应于catch
子句可以抛出e2无前导
catch
紧随其后的try语句块捕获e2或e2的超类型。除非e1是类例外。
所以看起来这就是你实际运行的犯规,但规范并不像14.21中的不可到达的catch块那样清晰。