【问题标题】: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 年的信息性问题!

标签: java exception runtimeexception


【解决方案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堆栈可以捕获它。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-09-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-12-31
        • 2020-06-15
        • 2020-03-27
        相关资源
        最近更新 更多