如何处理异常? catch Exception OR catch Throwable

By | 05月23日
Advertisement

在Java中,当你需要统一处理异常的时候,你是会选择catch (Exception),还是直接catch (Throwable)?

Java的异常体系

  • Throwable: Java中所有异常和错误类的父类。只有这个类的实例(或者子类的实例)可以被虚拟机抛出或者被java的throw关键字抛出。同样,只有其或其子类可以出现在catch子句里面。
  • Error: Throwable的子类,表示严重的问题发生了,而且这种错误是不可恢复的。
  • Exception: Throwable的子类,应用程序应该要捕获其或其子类(RuntimeException例外),称为checked exception。比如:IOException, NoSuchMethodException...
  • RuntimeException: Exception的子类,运行时异常,程序可以不捕获,称为unchecked exception。比如:NullPointException.

应该catch什么

其实只要是Throwable和其子类都是可以throw和catch的,那么如果在需要统一处理异常的地方,我们应该catch (Throwable th) 还是 catch (Exception)呢?

这两种处理的区别在于,catch throwable会把Error和其他继承Throwable的类捕捉到。而catch Exception只会捕捉Exception极其子类,捕捉的范围更小。先不考虑有其他的类继承了Throwable的情况下(附录A),第一种catch相当于比第二种catch多捕捉了把Error和其子类。

那么究竟Error是否需要捕捉呢?JDK中Error类的的注释(如下)里提到过,Error是一种严重的问题,应用程序不应该捕捉它。

An Error is a subclass of Throwable that indicates serious problems that a reasonable application should not try to catch. Most such errors are abnormal conditions. The ThreadDeath error, though a "normal" condition, is also a subclass of Error because most applications should not try to catch it.

A method is not required to declare in its throws clause any subclasses of Error that might be thrown during the execution of the method but not caught, since these errors are abnormal conditions that should never occur.

Java Lanuage Spec 7 中也提到:Error继承自Throwable而不是继承自Exception,是为了方便程序可以使用 "catch (Exception)"来捕捉异常而不会把Error也捕捉在内,因为Exception发生后可以进行一些恢复工作的,但是Error发生后一般是不可恢复的。

The class Error is a separate subclass ofThrowable, distinct from Exception in the class hierarchy, to allow programs to use the idiom "} catch (Exception e) { " (§11.2.3) to catch all exceptions from which recovery may be possible without catching errors from which recovery is typically not possible.

已经不难看出,Java本身设计思路就是希望大家catch Exception就足够了,如果有Error发生,catch了也不会有什么作用(附录B)。


引申,如何设计异常体系?

如何设计异常体系要根据你的项目的情况,类库框架,应用程序的异常设计方式都会有一些区别。下面简单谈谈个人对异常设计的一些看法

类库/框架

  • 继承RuntimeException扩展一个新的异常作为整个类库的异常基类。这个异常应该可以满足大部分类库对异常的要求。
  • 在实现中,在任何需要捕捉checked exception的地方都会把异常统一转化成这个新的异常。
  • 对于有特殊需求,需要自定义异常的,就通过继承这个基类来实现自定义异常。
  • 不对异常记录log(交给上层来处理)
  • 案例
    • fastjson 如何处理异常? catch Exception OR catch Throwable
    • spring 自定义异常比较多,不过都是继承自org.springframework.core.NestedRuntimeException,而这个异常也是继承自RuntimeException。

应用程序

  • 设计上和框架异常类似,只是在捕捉checked exception的时候需要log
  • 如果需要根据异常进行不同的处理,建议给自定义异常增加一个ERROR_CODE字段,这样无论在服务器还是客户端都可以根据不同的ERROR_CODE进行对应的处理。但是出现这种情况的时候,应该需要考虑一下设计思路了,一般来讲根据异常来决定业务流程不是一个好的设计方案。

附录A:是否应该直接继承Throwable来扩展新的异常?

个人认为异常都应该继承自Exception或者RuntimeException,而且Java本身对Exception和Error的规划就很清晰了,Java自己类库中没有异常是直接继承自Throwable的。

附录B:Error可以catch吗? 可以catch了后做些其他处理吗?

Error是可以catch的,而且也可以向常规Exception一样被处理,而且就算不捕捉的话也只是导致当前线程挂掉,其他线程还是可以正常运行,如果有需要的话捕捉Error之后也可以做些其他处理。但是Error是一种系统内部的错误,这种错误不像Exception一样是可能是程序和业务上的错误是可以恢复的。

假设进行网络连接操作的时候,IOException 发生了,可能是网络中断,我可以再尝试几次。

假设OutOfMemoryError发生了,就算被捕捉了,可以有什么手段让程序正常运行下去吗? 假设ExceptionInInitializerError发生了,类无法被正常初始化,这个是可以通过捕捉来恢复的吗?

Similar Posts:

  • JAVA Catch exception error.

    Java Catch 父类 Eclipse ---〉 Open Type (ctrl+shift+t ) , 查询 OutOfMemoryError extends VirtualMachineError , VirtualMachineError extends Error ,Error extends Throwable catch (Throwable e) catch (Exception e)

  • JAVA方法try{}..catch(Exception e){}详解

    try{ } catch(Exception e){ } 其实没有什么深奥的,try-catch就是监视try中的语句,如果抛出catch中声明的异常类型.比如ArrayIndexOutOfBoundsException就是数组越界的异常. 假设try中有语句int[] i=new int[10];如果你调用int[14]就一定会抛出ArrayIndexOutOfBoundsException这个异常,如果你写了try-catch且写了 catch(ArrayIndexOutOfBoundsEx

  • 异常控制try,catch用法小结

    1.基础介绍 try { //程序中抛出异常 throw value; } catch(valuetype v) { //例外处理程序段 } 语法小结:throw抛出值,catch接受,当然,throw必须在"try语句块"中才有效. 2.深入throw: (i).程序接受到throw语句后就会自动调用析构器,把该域(try后的括号内)对象clean up,然后再进 入catch语句(如果在循环体中就退出循环). 这种机制会引起一些致命的错误,比如,当"类"有指针成

  • 在zend framework框架中try{}catch(Exception e){}的跳转问题

    请勿盗版,转载请加上出处http://blog.csdn.net/yanlintao1 首先我先说明我遇到的问题 try{ //导入学生信息 $ModelStudent->insert($data2); } catch (Exception $e) { unlink(DOCS_PATH.'/student.xls'); $this->view->str = '导入失败,请检查数据格是否正确!'; $this->_forward("error","glo

  • try(........){throw new Exception("xxxxxx")}........catch(){.........}用法

    <?php function ActionSend($mobile, $key='') { try { /* if (empty($key)) { throw new Exception('key值不能为空'); } if($key != 'adfasdfdasfs') { throw new Exception('key值不一致'); } echo 'oo'; */ echo 1/0; echo "throw"; //throw new Exception ( "Me

  • 捕捉异常中try、catch和finally的执行顺序

    结论: 1.不管有木有出现异常,finally块中代码都会执行: 2.当try和catch中有return时,finally任会执行: 3.finally是在return表达式运算后前执行的,所以函数返回值是在finally执行前确定的: 4.finally中最好不要包含return,否则程序会提前退出,返回值不是try或catch中保存的返回值. 举例: 情况1:try{} catch(){} finally{} return; 显然程序按顺序执行. 情况2:try{ return; } ca

  • java中的异常类Exception

    异常的定义和使用方法咱就不说了,说点别的,有用的或者好玩的. 一.为什么要处理异常: 异常是导致程序中断运行的一种指令流,如果程序中有异常且不做任何处理的话,程序运行到异常处就会中断执行,直接结束程序,并将错误报告给用户.异常之后的语句也不再执行.为了保证程序的正常.完整运行,需要对异常进行处理. 二.Exception和Error: Java的异常体系中,最常用的就是Exception和Error,他们都是Throwable的子类. Exception:一般值程序中出现的问题,可以使用try-

  • Windows用户态程序高效排错 -- 异常(Exception)和通知(Debug Event)

    理解操作系统对程序的反馈:异常(Exception)和通知(Debug Event) 本小结首先介绍异常的原理和相关资料,再举例说明异常跟崩溃和调试是如何紧密联系在一起的.最后说明如何利用工具来监视异常,获取准确的信息. 2.3.1 异常(Exception)的方方面面和一篇字字珠玑的文章 异常是CPU,操作系统和应用程序控制代码流程的一种机制.正常情况下,代码是顺序执行的,比如下面两行: *p=11; printf("%d",*p); 这里应该会打印出11. 但若p指向的地址是无效地

  • 异常Caught exception while loading file struts-default.xml - [unknown location]解决办

    Struts2出现异常Caught exception while loading file struts-default.xml - [unknown location]解决办法 Caught exception while loading file struts-default.xml - [unknown location] at com.opensymphony.xwork2.config.providers.XmlConfigurationProvider.loadConfigurat

  • ARM 处理器如何处理异常

    ARM 处理器如何处理异常 当异常发生时,ARM处理器尽可能完成当前指令(除了复位异常)后,再去处理异常.并执行如下动作: 1. 进入与特定的异常相应的操作模式. 2. 将引起异常指令的下一条指令的地址保存到新模式的r14中. 3. 将CPSR的原值保存到新模式的SPSR中. 4. 通过设置CPSR的第7位来禁止IRQ.如果异常为快速中断.则还要设置CPSR的第6位来禁止快速中断. 5. 给PC强制赋向量地址值.

Tags: