在Java开发中,到处可见Exception或者它的子类。如何在一个已有的框架中或者自己的项目中利用好异常,而不让异常漫天飞,需要开发的积累和总结,这篇日志就为这个目的总结几年来的开发对异常使用总结吧。
首先认识Java异常体系结构,Java中使用Throwable作为所有的异常父类,下面有两大子类Error和Exception。所有的异常分为两种类型;一类为Checked异常,另一类为Unchecked异常。顾名思义,Checked异常就是需要程序代码必须捕获处理的,否则编译器就不让编译通过。Unchecked是不要求程序代码捕获处理的。其中继承Checked异常类的都为Checked类型异常,继承Unchecked类型的异常都为Unchecked类型异常。回过头来看Throwable的子类异常划分。其中Throwable直接子类Error和间接之类RuntimeException(Exception直接子类)为Unchecked异常,而其他的为Checked异常。下面分别描述各种异常的特点(摘录其他文档)。
Error系
Error类体系描述了Java运行系统中的内部错误以及资源耗尽的情形。应用程序不应该抛出这种类型的对象(一般是由虚拟机抛出)。如果出现这种错误,除了尽力使程序安全退出外,在其他方面是无能为力的。所以,在进行程序设计时,应该更关注Exception体系
Exception体系包括RuntimeException体系和非RuntimeException体系
RuntimeException:RuntimeException体系包括错误的类型转换、数组越界访问和试图访问空指针等等。处理 RuntimeException的原则是:如果出现RuntimeException,那么一定是程序员的错误。例如,可以通过检查数组下标和数组边界 来避免数组越界访问异常。
其他非RuntimeException(IOException等等):这类异常一般是外部错误,例如试图从文件尾后读取数据等,这并不是程序本身的错误,而是在应用环境中出现的外部错误。
因为很多API和框架,在接口上面申明Checked异常,所以我自己的代码中到处是Catch,而且很多Catch到的异常是没法处理掉的,假如我一层一层的抛出去,这样就影响性能,污染接口(比如MVC的控制层不可能去处理你的JDBC链接异常),而且上层用户代码也不见得可以处理。而且也影响美观,增加各层代码复杂度。后来我有一段时间都是不管三七二十一,大部分异常我都使用Unchecked异常包装后抛出去。但是Java规范推荐的是使用Checked异常,这点我现在都觉得值得商榷。再后来,在使用Unchecked异常时也觉得有时候应该让上层的代码处理这个异常,获取出现错误的信息。(比如:用户调用接口,本因该是正数而不是负数,不能只是返回值说处理失败),而且异常最好是有分类,比如JDBC连接异常,我们不能处理就抱装成系统级别的Unchecked异常,如果是参数错误这样的异常,我们定义为系统级别的Checked,如果是用户密码错误这种异常,我们定义为业务级别的Checked异常。我们经常在业务方法上面定义业务基本的Checked异常。
我们经常在处理异常的时候都伴随着记录异常日志信息。日志信息如果记录比较好,我经常看到,开发人员为了记录住全部异常信息都是Catch的时候都是Log.warn("某某",cause),弄等日志信息重复记录,因为你记录后抛出去又被catch一次,这里我自己常用的一个原则,就是那里发生异常那里记录我catch项目组其他人的接口的异常时我不记录,我要么处理,要么抛出去(这里可能没说清楚,就是离发生异常就近原则;比如我的持久层就是包装好jdbc异常。记录好日志)。
下面总结几条我个人异常设计原则或者编码原则
能够处理的异常坚决使用Checked异常包装
不能处理、不可恢、复严重错位的异常使用Unchecked包装,接口上面说明可能的Unchecked异常,让调用者知道
包装的异常信息栈要连续,能够被追踪到异常发生地(比如new CustomerException("某某", cause),不要使用 new CustomerException("某某"))
包装后的异常要分业务异常或者系统异常而且必须要有一定的业务或者系统含义
利用JDK中已有的异常,不重复造车
记录异常日志时,就近异常发生地记录,不要重复记录,当然如果是可以处理的异常就不要记录日志,比如用户输入的数据有问题不能类型转换。就没必要记录,你可以处理——让用户重新输入一遍
程序的最上层要对unchecked异常统一处理,不要暴露给用户
针对JEE通常用的三层架构,dao层,基本会在每个接口后面声明Unchecked异常。service层会在大部分接口后面声明checked异常。action会校验用户输入参数、并把业务异常信息转换用户看得懂的消息。
初次在oschina上发帖,大家多给点建议、拍砖,但不要骂人