JAVA异常处理小结

最近一个月都在做demo,对Java的异常处理有了一点感受,小结在这里,其他语言中的异常处理也基本类同:

1、异常分类

Java的异常分为RuntimeException、Exception两种,还有一种错误是Error。编译器强制程序员处理Exception异常。

RuntimeException一般是编程中的错误导致的,如NullPointer、ArrayIndexOutOfBounds等。导致这种异常的原因通常是代码中的逻辑错误或者没有对当前代码外部传递进来的引用进行必要的检查导致的,所以一般不要去catch这种异常、更不要试图恢复这些异常,否则测试中可能会忽视相应的编程错误和漏洞。

Error一般是系统错误,这些错误很可能不是代码本身的错误导致的,如非必要可以不管它,处理得不当可能让一些系统问题被忽视。

Execption及其子异常类的对象是必须要程序员来处理的。Exception的恰当处理可以使得程序更加健壮和可维护。

2、Exception处理

处理Exception应该注意以下几点:

a. 在代码中,不要随处都是try catch

程序员应该清楚什么样的异常应该在当前的代码中处理,什么样的异常应该交给调用者处理。我感觉处理异常应该有层次感,底层的代码通常以抛出为主,在系统的某些特定层次比较集中地处理某一类或某几类异常。

b. 不要使用Exception来catch所有异常

用Exception catch住所有异常之后,除了print或者log一下异常的信息以外基本上什么也做不了。catch住异常是为了做出处理、使得系统恢复到正常的状态,print或者log异常信息只是调试代码的一种手段,不应该出现在健壮的代码中。Java之所以支持一个方法抛出五花八门的各式异常,就是为了让调用的程序员有针对性地进行处理。

c. 不要使用太大的try语句块

使用一个包罗万象的try语句块,常常意味着之后会有一个庞大、复杂的catch,使得代码丑陋而不可维护(比如:以后对try语句块中的代码的修改很可能会殃及后面那个尾大不掉catch语句块)。更重要的是,在catch中很难确定到底是什么地方发生了异常,因为同样一个异常可能在try语句块的不同位置被多次抛出,这样就很难有针对性地处理异常。

d. 在finally中释放资源

当try语句块中代码申请了系统中的资源(如输入输出流、数据库连接、网络连接)时,应该尽量在finally中释放资源、这使得代码清晰、便于维护,随处释放资源不仅仅是使得代码不好维护,还很容易造成疏忽、留下安全漏洞(例如有些资源没有被正确释放、有些资源被重复释放)。

e. 不要试图用try catch来控制程序的执行流程

例如不要用try catch来检查一个字符串是否可以转化成数字,这是自定义的检查函数或者正则表达式应该干的事。java运行时环境捕获异常并改变处理流程需要大量的堆栈操作,用于流程控制会使得系统效率下降、健壮性降低。

这些都是基本的注意事项,其中b和c经常是相伴出现在糟糕的异常处理代码中的。更高级一点地,可以使用有意义的自定义异常,以及在catch到当前代码不应处理的异常后、将异常转义成意义更加明确的其他类型的异常并抛出。

标签