一. 两种异常
RuntimeException:非检查异常,如NullPointerException,IndexOutBoundsExceptio,Java编译器不要求必须进行异常捕获或者抛出声明,由程序员自行决定
非运行时异常:检查异常,Java编译器强制程序员必须进行捕获处理,如IOException,SQLException,如果不进行捕获或者抛出声明处理,编译都不会通过
二. 三种方法
1)try..catch进行异常捕获
2)在方法体外利用throws抛出异常,告知调用者这段代码可能会出现异常
2.1 抛出的异常是非运行异常,此方法的调用者必须显示的用try..catch捕获或是继续向上抛出异常
2.2 若是运行时异常,此方法的调用者可以选择性的进行异常捕获处理
3)代码块中用throw手动抛出一个异常对象
3.1 抛出的异常对象是非运行时异常,此方法调用者需显示的用try..catch进行捕获或者向上抛出异常
注:
被try块包围的代码说明这段代码可能会发生异常,一旦发生异常,异常变回被catch捕获到,然后需要在catch块中进行异常处理
throw和throws是抛出异常,让调用者去处理,自己不进行具体的处理
3.2 运行时异常,调用者可以选择性的进行异常捕获
三. 几个关键字
1)try用来包围可能出现的异常逻辑代码,无法单独使用,必须配合catch或者finally使用,可以有一下形式
try…catch…,try…finally…,try…catch…finally…
try块只能有一个,catch块可以有多个,finally块是可选的,最多能有一个,catch是对异常进行处理,在有异常的情况下会进入catch块,finally块无论什么情况下都会执行的;当存在多个catch块的时候,是按catch块的先后顺序进行匹配的,一旦异常与其中一个catch块匹配,则不会与后面的catch块进行匹配
注:在使用try...catch...finally,要慎重再finally块中使用return,因为finally中的return会覆盖已有的返回值。
2)throws出现在方法的声明中,表示该方法可能会出现异常,然后交给上层调用它的方法程序进行处理,允许后面跟多个异常类型;
表示会出现异常的可能性,并不一定会产生异常
3)throw只会出现在方法体中,当方法在执行的过程中遇到某种异常情况,将异常消息封装为异常对象,然后throw出去;(throw可以进行异常类型转换)
一定是出现了某种异常,然后抛出突出刚
四. 异常抛出声明
子类重写父类方法,确定异常抛出声明的类型的三点原则:
1)父类的方法没有声明异常,子类在重写该方法的时候不能声明异常
2)父类方法声明了一个异常exception1,则子类在重写该方法的时候声明的异常不能是exception1的父类
3)如果父类声明的异常只有非运行时异常(运行时异常),则子类在重写该方法的时候声明的异常也只能有非运行时异常(运行时异常),不能有运行时异常(非运行时异常)
五. 注意
1)慎重使用异常,不要用异常区控制程序的流程
2)切忌使用空catch块,相当于在捕获了异常后什么都不做,相当于忽略了这个异常,意味着在程序中隐藏了错误和异常,并且很可能导致程序出现不可控的执行结果。如果非常肯定捕获到的异常不会以任何方式对程序造成影响,最好用Log日志将该异常进行记录,以便日后方便更新和维护。
3)异常抛出的旋转(检查异常还是非检查异常)
4)注意catch块的顺序,不要把上层类的异常放在最前面的catch块上,否则对于下层catch块永远无法匹配
5)不要将提供给用户看的信息放在异常信息里,比较好的方式是将所有错误提示信息放在一个配置文件中统一管理。
6)避免多次在日志中记录同一个异常,否则可能无从查找异常发生的根源
7)异常处理尽量放在高层进行,尽量将异常抛给上层调用者。若在每个出现异常的地方都直接进行处理,会导致程序异常处理流程混乱,不利于后期维护和异常错误排查
8)在finally中释放资源,若有使用文件读取,网络操作以及数据库操作等,记得在finally中释放资源。这样可以使程序占用更少的资源,也可以避免因为资源未释放二发生的异常。