关于使用异常的一些总结

我在现在的项目中,经常会遇到各种通过异常来控制流程,以及通过异常来对前端输出提示信息的情况。在这期间碰到了很多问题,也做了一些经验总结;接下来我为大家分享下个人心得。


一、RuntimeException与Exception的区别以及用途

RuntimeException是运行时异常,也叫未检测的异常(unchecked exception),这种异常通常是可以避免发生的,他的出现很多情况是由于开发人员粗心导致的。例如:NullPointerException,空指针异常就是一种非常典型的RuntimeException,这是一种日常开发中经常会遇到的异常,当我们粗心的调用了空对象的属性方法时,系统就会抛出NullPointerException,但是这是可以避免的,我们可以通过非空判断,来避免调用空对象的属性方法。RuntimeException比较特殊的地方在于,即使你没有捕获异常(try catch),IDE通常也不会强制要求你抛出它;但是比较规范的做法是:如果你没有捕获异常,那么最好将异常抛出(throws),这样做的目的是方便以后调用方法的人能够明确的知道,调用该方法将会遇到哪儿些风险,以及如何处理它。

Exception是编译时异常,也叫需检测的异常(checked exception),这种异常通常是我们在代码中难以规避的。例如:在进行文件读写时出现文件损坏或者硬盘坏道等不可抗因素,那么这种情况是我们在代码中难以规避的,所以此时需要抛出需检测的异常,例如IOException,以便告诉调用者调用方法时可能会出现的风险。

二、抛出异常还是捕获异常

当前方法中出现需要处理的异常时,我们不应该立即捕获异常,而是应该判断下,当前方法的调用者是否需要处理该异常,如果不需要,那我们就可以立即处理它,否则我们需要将其抛出。例如:我们在对象复制的时候,通常会在方法(假设方法名为copy)中根据源对象的字段名找到目标对象的字段,当没有找到对应字段时,Field对象的getDeclaredField方法通常会抛出NoSuchFieldException。如果你十分的确认copy方法的调用者不需要处理该异常,那么这个时候你可以立马处理它(例如通过log输出一些警告信息),否则你应该抛出该异常,让调用者自己处理此异常。

接口开发中,如果需要使用异常来向前端输出一些校验信息的话(比如登录时密码错误等),那么我们需要对这种情况专门设置一个异常,例如VerifyException;我们为VerifyException额外设置一个errorcode字段,并为其重写fillInStackTrace方法,如下图。处理异常时,除VerifyException以外的异常我们都当做是系统异常来处理,传给前端的状态码统一为500(成功为200),表示系统错误;当遇到VerifyException时,我们则将定义在VerifyException中errorcode作为状态码返回,这样子前端在接收到不同的状态码时就可以完成不同的操作,比如登录时errorcode=300表示用户输入的密码错误等。

关于使用异常的一些总结

 

需要注意的是不要想着在所有场景下都用一种异常来处理,我们应该针对不同的情况抛出不同的异常(在以前的开发中,我就总犯这个错误)。例如:业务异常我们就该抛出BusinessException,空值异常就该抛出NullValueException等等。