java程序的151个建议-提倡异常封装,采用异常链传递异常
Posted 你是我的天晴
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java程序的151个建议-提倡异常封装,采用异常链传递异常相关的知识,希望对你有一定的参考价值。
Java语言的异常处理机制可以确保程序的健壮性,提高系统的可用率,但是Java API提 供的异常都是比较低级的(这里的低级是指“低级别”的异常),只有开发人员才能看得懂, 才明白发生了什么问题。而对于终端用户来说,这些异常基本上就是天书,与业务无关,是纯计算机语言的描述,那该怎么办?这就需要我们对异常进行封装了。异常封装有三方面的 优点:
(1) 提髙系统的友好性
例如,打开一个文件,如果文件不存在,则会报FileNotFoundException异常,如果该 方法的编写者不做任何处理,直接抛到上层,则会降低系统的友好性,代码如下所示:
public static void doStuffO throws Exception
InputStream is = new FileInputStreani("无效文件.txt");
/*文件操作*/
此时doStuff方法的友好性极差:出现异常时(比如文件不存在),该方法会直接把 FileNotFoundException异常抛出到上层应用中(或者是最终用户),而上层应用(或用户) 要么自己处理,要么接着抛,最终的结果就是让用户面对着“天书”式的文字发呆,用户不知道这是什么问题,只是知道系统告诉他“哦,我出错了,什么错误?你自己看着办吧”。
解决办法就封装异常,可以把异常的阅读者分为两类:开发人员和用户。开发人员査找问题,需要打印出堆栈信息,而用户则需要了解具体的业务原因,比如文件太大、不能同时 编写文件等,代码如下:
public static void doStuff2() throwsMyBussinessException
try
InputStream is = new FilelnputStream (n无效文件.txt"〉;
catch (FileNotFoundException e)
//为方便开发和维护人员而设置的异常信息
e.printstackTrace();
//抛出业务异常
throw new MyBussinessException (e);
(2)提高系统的可维护性 来看如下代码:
public void doStuff()
try
//do something
catch(Exception e)
e.printstackTrace();
这是很多程序员容易犯的错误,抛出异常是吧?分类处理多麻烦,就写一个catch块来 处理所有的异常吧,而且还信誓旦旦地说“JVM会打印出栈中的出错信息”,虽然这没错, 但是该信息只有开发人员自己才看得懂,维护人员看到这段异常时基本上无法处理,因为需要深入到代码逻辑中去分析问题。
正确的做法是对异常进行分类处理,并进行封装输出,代码如下:
public void doStuff()
try
//do something
catch(FileNotPoiindException e)
log.info("文件未找到,使用默认釔置文件............. ");
catch(SecurityException e)
log.error "无权访问,可能原因是........... ");
e.printStackTrace();
如此包装后,维护人员看到这样的异常就有了初步的判断,或者检査配置,或者初始化环境,不需要直接到代码层级去分析了^
(3)解决Java异常机制自身的缺陷
Java中的异常一次只能抛出一个,比如doStuff方法有两个逻辑代码片段,如果在第一 个逻辑片段中抛出异常,则第二个逻辑片段就不再执行了,也就无法抛出第二个异常了,现 在的问题是:如何才能一次抛出两个(或多个)异常呢?
其实,使用自行封装的异常可以解决该问题,代码如下:
class MyException extends Exception
//容纳所有的异常
privateList<Throwable> causes = new ArrayList<Throwable>();
//构造函数,传速一个异常列表
public MyException(List<? extends Throwable> causes)
causes.addAll(causes);
//读取所有的异常
public Iist<Throwable> getExceptions()
return causes;
//MyExcepticm异常只是一个异常容器,可以容纳多个异常,但它本身并不代表任何异常含义,它所解决的是一次抛出多个异常的问题,具体调用如下:
public static void doStuffO throwsMyException
List<Throwable> list = new ArrayList<Throwable>();
//第一个逻辑片段
try
//Do Something
catch(Exception e)
list.add(e);
//第二个逻辑片段
try
// Do Something
catch(Exception e)
list.add(e);
//检查是否有必要抛出异常
if (list.size() > 0)
throw new MyBxception(list);
这样一来,doStuff方法的调用者就可以一次获得多个异常了,也能够为用户提供完整 的例外情况说明。可能有读者会问:这种情况可能出现吗?怎么会要求一个方法抛出多个异常呢?
绝对可能出现,例如Web界面注册时,展现层依次把Usei•对象传递到逻辑层,Register 方法需要对各个Field进行校验并注册,例如用户名不能重复,密码必须符合密码策略等, 不要出现用户第一次提交时系统提示“用户名重复”,在用户修改用户名再次提交后,系统又提示“密码长度少于6位”的情况,这种操作模式下的用户体验非常糟糕,最好的解决办 法就是封装异常,建立异常容器,一次性地对User对象进行校验,然后返回所有的异常。
以上是关于java程序的151个建议-提倡异常封装,采用异常链传递异常的主要内容,如果未能解决你的问题,请参考以下文章
编写高质量代码:改善Java程序的151个建议(第8章:异常___建议110~113)
转载--编写高质量代码:改善Java程序的151个建议(第3章:类对象及方法___建议36~40)