异常
1.Throwable
Throwable是所有异常的基类,它有两个子类Error和Exception。
Error表示系统错误或资源耗尽,由Java系统自己使用,应用程序不应抛出和处理,比如图中列出的虚拟机错误(VirtualMacheError)及其子类内存溢出错误(OutOfMemoryError)和栈溢出错误(StackOverflowError)。
Exception表示应用程序错误,它有很多子类,应用程序也可以通过继承Exception或其子类创建自定义异常,图中列出了三个直接子类:IOException(输入输出I/O异常),SQLException(数据库SQL异常),RuntimeException(运行时异常)。
RuntimeException(运行时异常)比较特殊,它的名字有点误导,因为其他异常也是运行时产生的,它表示的实际含义是unchecked exception (未受检异常),相对而言,Exception的其他子类和Exception自身则是checked exception (受检异常),Error及其子类也是unchecked exception。
checked还是unchecked,区别在于Java如何处理这两种异常,对于checked异常,Java会强制要求程序员进行处理,否则会有编译错误,而对于unchecked异常则没有这个要求。
定义这么多的异常类,其实并没有比父类多多少的属性和方法,继承父类也就是定义了几个构造方法并调用父类的几个构造方法而已,主要就是让每个异常都脊梁有自己的名字,有助于代码的可读性和维护性。
2.自定义异常
在前后端分离的开发模式中我们童话村那个要做的就是全聚德异常处理,其中就要进行自定义的异常,继承Exception或者说Exception的某一个子类,自定义异常一般都是受检异常,就是开发人员需要自己去进行异常处理。
3.try-catch-finally
try{
//可能触发异常A,B代码
}catch(Exception e){
//捕获异常
}finally{
//不管有没有异常都执行
}
finally:一版由于释放一些资源
- 如果没有异常发生,在try内的代码执行结束后执行。
- 如果有异常发生且被catch捕获,在catch内的代码执行结束后执行
- 如果有异常发生但没被捕获,则在异常被抛给上层之前执行。
重点:
- finally语句的执行细节如果在try或者catch语句内有return语句,那么就是return语句在finally执行结束后执行,但finally并不能改变返回值
- 如果在finally语句中也有返回值,那么不仅会覆盖try-catch中的return,而且还会掩盖try-catch内的返回值,就像异常没有发生过一样。比如:
public static int test(){
int ret=0
try{
int a=5/0;
return ret;
}finally {
return 2;
}
}
上面这个代码就不会报错,而是返回finally里面的return。
- 如果说finally中抛出异常了,try-catch里面的异常就会被覆盖。所以说早finally语句汇总应该避免室友return和抛出异常。
4.try-catch-resources
这中异常处理方式一般就在数据库连接或者说文件流,首先打开资源,然后在finally中调用资源的关闭方法。其实用try-catch-finally也是可以,这种一般用的比较少哈。
6.throws
用于声明一个方法可能抛出的异常,用法如下:
public void test() throws AppException, SQLException, NumberFormatException {
//主体代码
}
对于受检异常就是不可以抛出而不声明,但可以声明抛出但是实际不抛出,就是在父类声明在子类抛出。
如果一个方法内调用了另一个声明抛出checked exception的方法,则必须处理这些checked exception,不过,处理的方式既可以是catch,也可以是继续使用throws,如下代码所示:
public void tester() throws AppException {
try {
test();
} catch (SQLException e) {
e.printStackTrace();
}
}
对于test抛出的SQLException,这里使用了catch,而对于AppException,则将其添加到了自己方法的throws语句中,表示当前方法也处理不了,还是由上层处理,这就是所谓的向上传递异常,哈哈哈。
7.异常处理的逻辑
如果自己知道怎么处理异常,就进行处理,如果可以通过程序自动解决,就自动解决,如果异常可以被自己解决,就不需要再向上报告。
如果自己不能完全解决,就应该向上报告。如果自己有额外信息可以提供,有助于分析和解决问题,就应该提供,可以以原异常为cause重新抛出一个异常。
总有一层代码需要为异常负责,可能是知道如何处理该异常的代码,可能是面对用户的代码,也可能是主程序。如果异常不能自动解决,对于用户,应该根据异常信息提供用户能理解和对用户有帮助的信息,对运维和程序员,则应该输出详细的异常链和异常栈到日志。
有了异常机制后,程序的正常逻辑与异常逻辑可以相分离,异常情况可以集中进行处理,异常还可以自动向上传递,不再需要每层方法都进行处理,异常也不再可能被自动忽略,从而,处理异常情况的代码可以大大减少,代码的可读性、可靠性、可维护性也都可以得到提高。