如何解释Exception是不是会捕获RuntimeException?

Posted

技术标签:

【中文标题】如何解释Exception是不是会捕获RuntimeException?【英文标题】:How to explain whether Exception will catch RuntimeException?如何解释Exception是否会捕获RuntimeException? 【发布时间】:2013-10-10 10:28:30 【问题描述】:

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

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

但是

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

我知道RuntimeException 的特殊之处在于它没有被选中。但据我了解,这仅适用于是否必须声明异常,而不是它们是否被捕获。即便如此,我也不知道为什么这个逻辑会在捕获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),我认为是因为继承的语法错误?

【问题讨论】:

您应该编辑问题标题 - 如果有人只看标题,他们会认为捕获异常不会捕获运行时异常。 @AlexCiminian 好点。这是另一个 8 年的信息性问题! 【参考方案1】:
catch (Exception ex)  ... 

捕获 RuntimeException。

无论你放在 catch 块中的什么东西都会被捕获,它的子类也会被捕获。

【讨论】:

【参考方案2】:

问题的前提是有缺陷的,因为捕捉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(如果它是一个集合而不是一个数组)

也许这就是你所看到的?

【讨论】:

重读我的代码。这是正确的。我的绝缘层有问题,因为运行时异常来自 if(results.foo.bar()) /* apply callback */ ,这是一个 NPE。 @djechlin:你的帖子没有显示 if (results.foo.bar()) - 目前还不清楚你实际上在问什么...... 查看我下面的帖子,Exception 没有捕获运行时异常。【参考方案3】:

捕获Exception 将捕获RuntimeException

【讨论】:

【参考方案4】:

我遇到了类似的情况。这是因为 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 也会捕获运行时异常。

【讨论】:

【参考方案5】:
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

【讨论】:

抛出 RuntimeException 的线程不是试图捕获异常的线程。这与它是否是 RuntimeException 无关。您的 main 方法已成功中断线程,所以 that try 块没有什么可捕获的。然后有一个单独的RuntimeException 被抛出堆栈并且没有被任何东西(在用户代码中)捕获,因为没有任何东西in堆栈可以捕获它。

以上是关于如何解释Exception是不是会捕获RuntimeException?的主要内容,如果未能解决你的问题,请参考以下文章

如何捕获 I/O 异常(确切地说是 I/O,而不是 std::exception)

Java如何捕获应用程序的Runtime error

19.10.23

JAVA捕获MYSQL主键冲突异常 示例如Exception ex 对应的异常 如何捕获,只要捕获,求满意答案

托管 CLR 时如何捕获 ***Exception 并从中恢复

java编程用catch(Exception e)捕获异常,在catch中用instanceof对不同的异常分别处理