为什么不捕获Exception catch RuntimeException?

时间:2013-10-03 16:10:42

标签: java exception runtimeexception

这对我来说很奇怪。 RuntimeException继承自Exception,继承自Throwable

catch(Exception exc) { /* won't catch RuntimeException */

catch(Throwable exc) { /* will catch RuntimeException */

我知道RuntimeException很特别,因为它未被检查。但据我所知,这仅适用于是否必须声明例外,而不是它们是否被捕获。即便如此,我也不知道为什么这种逻辑会在捕捉Throwable时失败。

这与我非常相关,因为我遇到了可以在终端操作中抛出RuntimeExceptions的情况。我不确定这个模式的名称,但类似于我的班级EmailRoller采用Callbacks的数组。代码如下所示:

for(Callback cb : callbacks) {
    try {
        cb.call(item);
    }
    catch(Exception exc) {
        logger.error("Error in callback: ", exc);
   }
}

所以这是一个像OOME这样的东西需要通过的情况,因为如果其中一个回调消耗所有的机器内存,那肯定会影响其他的运行。但是NullPointerException?或IndexOutOfBoundsException?这些会影响回调,但不会阻止其他人运行。

此外,这是一个企业设计。不同的程序员或团队可以添加回调来处理项目,但它们应该彼此隔离。这意味着,作为负责将这些回调相互隔离的程序员,我不应该依赖它们来确保错误不会漏掉。抓取Exception应该是正确的,但不是因为RuntimeException滑过。所以我更普遍的问题是:这里有什么好的模式?只是catch(Exception | RuntimeException exc),我认为由于继承而导致语法错误?

5 个答案:

答案 0 :(得分:111)

问题的前提是有缺陷的,因为抓住Exception 抓住RuntimeException。演示代码:

public class Test {
    public static void main(String[] args) {
        try {
            throw new RuntimeException("Bang");
        } catch (Exception e) {
            System.out.println("I caught: " + e);
        }
    }
}

输出:

I caught: java.lang.RuntimeException: Bang

如果出现以下情况,您的循环将出现问题:

  • callbacks为空
  • 在循环执行时修改callbacks的任何内容(如果它是集合而不是数组)

也许这就是你所看到的?

答案 1 :(得分:23)

catch (Exception ex) { ... }

捕获RuntimeException。

无论你在catch块中放入什么,都会被捕获,以及它的子类。

答案 2 :(得分:8)

抓取Exception会抓住RuntimeException

答案 3 :(得分:3)

我遇到了类似的情况。之所以发生这种情况,是因为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(){}
}

是的...捕捉Exception也会捕获运行时异常。

答案 4 :(得分:-2)

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);
        }  

    }  
}

它的输出不包含test2,因此它不处理运行时异常。 @jon双向飞碟,@ Jan Zyka