Java 为什么捕获异常不捕获运行时异常?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19164020/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why doesn't catching Exception catch RuntimeException?
提问by djechlin
This is very odd to me. RuntimeException
inherits from Exception
, which inherits from Throwable
.
这对我来说很奇怪。RuntimeException
继承自Exception
, 继承自Throwable
.
catch(Exception exc) { /* won't catch RuntimeException */
but
但
catch(Throwable exc) { /* will catch RuntimeException */
I know RuntimeException
is special in that it's unchecked. But to my understanding that applies just to whether exceptions have to be declared, not whether they are caught. And even then, I don't know why this logic would break on catching Throwable
.
我知道RuntimeException
它的特殊之处在于它未经检查。但据我所知,这仅适用于是否必须声明异常,而不适用于它们是否被捕获。即便如此,我也不知道为什么这种逻辑会在 catch 时中断Throwable
。
This is pretty relevant to me since I have a situation where RuntimeException
can be thrown in a terminal operation. I'm not sure the name for this pattern, but something like, my class EmailRoller
takes an array of Callbacks
. The code looks like this:
这与我非常相关,因为我有一种RuntimeException
可以在终端操作中抛出的情况。我不确定这个模式的名称,但类似的,我的类EmailRoller
需要一个Callbacks
. 代码如下所示:
for(Callback cb : callbacks) {
try {
cb.call(item);
}
catch(Exception exc) {
logger.error("Error in callback: ", exc);
}
}
So this is a case where something like an OOME needs to fly through, because if one of these callbacks consumes all machine memory, that sure as heck is going to affect the running of the other ones. But a NullPointerException
? Or an IndexOutOfBoundsException
? Those will affect the callback but won't prevent the others from running.
所以这是一个像 OOME 这样的东西需要飞过的情况,因为如果这些回调中的一个消耗了所有机器内存,那肯定会影响其他回调的运行。但是一个NullPointerException
? 还是IndexOutOfBoundsException
? 这些会影响回调,但不会阻止其他人运行。
Also, this is a bit of an enterprise design. Different programmers or teams can add callbacks to process the item, but they should be isolated from each other. This means, as the programmer responsible for insulating these callbacks from each other, I shouldn't rely on them to make sure errors don't slip through. Catching Exception
should be about the right line, but it isn't because RuntimeException
slips through. So my more general question is: what's a good pattern here? Just catch(Exception | RuntimeException exc)
, which I believe is a syntax error because of the inheritance?
此外,这有点像企业设计。不同的程序员或团队可以添加回调来处理项目,但它们应该相互隔离。这意味着,作为负责将这些回调相互隔离的程序员,我不应该依赖它们来确保不会出现错误。接球Exception
应该是正确的路线,但这不是因为RuntimeException
漏掉了。所以我更普遍的问题是:这里有什么好的模式?Just catch(Exception | RuntimeException exc)
,我认为这是由于继承而导致的语法错误?
采纳答案by Jon Skeet
The premise of the question is flawed, because catching Exception
doescatch RuntimeException
. Demo code:
问题的前提是有缺陷的,因为catchException
确实catch RuntimeException
。演示代码:
public class Test {
public static void main(String[] args) {
try {
throw new RuntimeException("Bang");
} catch (Exception e) {
System.out.println("I caught: " + e);
}
}
}
Output:
输出:
I caught: java.lang.RuntimeException: Bang
Your loop will have problems if:
如果出现以下情况,您的循环就会出现问题:
callbacks
is null- anything modifies
callbacks
while the loop is executing (if it were a collection rather than an array)
callbacks
一片空白callbacks
循环执行时任何修改(如果它是一个集合而不是一个数组)
Perhaps that's what you're seeing?
也许这就是你所看到的?
回答by Jan Zyka
catch (Exception ex) { ... }
WILLcatch RuntimeException.
将捕获运行时异常。
Whatever you put in catch block will be caught as well as the subclasses of it.
无论您在 catch 块中放入什么,都将被捕获以及它的子类。
回答by cmd
Catching Exception
will catch a RuntimeException
捕捉Exception
会捕捉到RuntimeException
回答by rajya vardhan
I faced similar scenario. It was happening because classA's initilization was dependent on classB's initialization. When classB's static block faced runtime exception, classB was not initialized. Because of this, classB did not throw any exception and classA's initialization failed too.
我遇到过类似的情况。这是因为 classA 的初始化依赖于 classB 的初始化。当 classB 的静态块遇到运行时异常时,classB 没有被初始化。因此,classB 没有抛出任何异常,classA 的初始化也失败了。
class A{//this class will never be initialized because class B won't intialize
static{
try{
classB.someStaticMethod();
}catch(Exception e){
sysout("This comment will never be printed");
}
}
}
class B{//this class will never be initialized
static{
int i = 1/0;//throw run time exception
}
public static void someStaticMethod(){}
}
And yes...catching Exception
will catch run time exceptions as well.
是的……捕获Exception
也会捕获运行时异常。
回答by Kabs
class Test extends Thread
{
public void run(){
try{
Thread.sleep(10000);
}catch(InterruptedException e){
System.out.println("test1");
throw new RuntimeException("Thread interrupted..."+e);
}
}
public static void main(String args[]){
Test t1=new Test1();
t1.start();
try{
t1.interrupt();
}catch(Exception e){
System.out.println("test2");
System.out.println("Exception handled "+e);
}
}
}
Its output doesn't contain test2 , so its not handling runtime exception. @jon skeet, @Jan Zyka
它的输出不包含 test2 ,所以它不处理运行时异常。@jon skeet,@Jan Zyka