java异常体系中,所有异常都继承至java.lang.Throwable。从异常的严重性,可恢复程度上,被分为了以下两类:
- java.lang.Error
Error及其子类代表的异常通常指的是毁灭性的、不可恢复的异常,如常见的虚拟机异常类:OutOfMemory、StackOverflow,线程死了、IOError等。 - java.lang.Exception
Exception及其子类代表的异常表示的是可恢复的异常,即可以经过程序处理后使其继续正常工作。Exception有个比较特殊的子类:java.lang.RuntimeException,这个异常及其子类代表的是运行时异常,官方解释是虚拟机运行时候进行一些常规操作可能会抛出的异常。
Throwable类中,cause中包含了具体的异常类。比如我们针对代码中的NullPointException封装成了自己的ServiceException,则会把原始异常放入值cause中。
statckTrace:方法的调用链,包含每次调用的具体类和代码所在行数,其获取方式是getStackTrace方法,这是个本地方法,依赖于具体的平台。
detailMessage:对这次异常的一个描述信息,外部通过getMessage方法获取此属性。
SUPPRESSED_SENTINEL:jdk1.7之后新增加的属性,当一个方法里面产生了多个异常的时候,以前最新产生的一个异常会把之前的异常覆盖掉。增加了这个属性后,可以调用最终要抛出的异常对象的addSuppressed方法,把之前的异常添加进来。
从是否需要强制要求调用者处理该异常层面上,异常被分为了以下两类:
- CheckException
方法签名中必须显式throws该异常,调用者必须try catch处理该异常 - UnCheckedException
方法签名中无须显式throws该异常,调用者无须try catch处理该异常
这里需要特别注意的是,如果在代理对象的执行方法中抛出了一个CheckedException(也可能是某个切面执行程序抛出的异常),而方法签名中未显式throws该异常,则异常会被变成java.lang.reflect.UndeclaredThrowableException异常,原始异常可能会看不到了。虽然java规范中要求checkedException必须显式在方法签名中抛出,编译时候也会针对该项进行检查,但是代理对象这块的语法检测机制无法检测到。