63

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

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

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

我知道RuntimeException它的特别之处在于它是未经检查的。但据我了解,这仅适用于是否必须声明异常,而不是它们是否被捕获。即使那样,我也不知道为什么这种逻辑会在 catch 时中断Throwable

这与我非常相关,因为我有一种情况RuntimeException可以在终端操作中抛出。我不确定这种模式的名称,但类似于,我的类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),我认为这是因为继承的语法错误?

4

5 回答 5

153

问题的前提是有缺陷的,因为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);
        }
    }
}

输出:

I caught: java.lang.RuntimeException: Bang

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

  • callbacks一片空白
  • 循环执行时任何修改callbacks(如果它是一个集合而不是一个数组)

也许这就是你所看到的?

于 2013-10-03T16:13:40.297 回答
29
catch (Exception ex) { ... }

捕获 RuntimeException。

无论您放入 catch 块中的任何内容以及它的子类都会被捕获。

于 2013-10-03T16:12:46.290 回答
12

Exception会抓到RuntimeException

于 2013-10-03T16:16:37.007 回答
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也会捕获运行时异常。

于 2015-12-02T09:34:42.610 回答
-3
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 skeet,@Jan Zyka

于 2018-04-05T08:02:45.490 回答