一、异常的概念和体系结构
1、异常的概念
在Java中,将程序执行过程中发生的不正常行为称为异常,常见的有算术异常,数组越界异常,空指针异常
2、异常的体系结构
从上图中可以看到:
1.Throwable:是异常体系的顶层类,其派生出两个重要的子类,Error和Exception
2.Error:指的是Java虚拟机无法解法的严重问题,比如:JVM的内部错误、资源耗尽等,典型代表:StackOverflowError和OutOfMemoryError,一旦发生无力回天。
3.Exception:异常产生后程序员可以通过代码进行处理,使程序继续执行。比如:感冒、发烧。我们平时所说的异常就是Exception。
3.异常的分类
分为编译时异常(受检查异常)和运行时异常(非受检查时异常)
二、异常的处理
1、防御式编程
★LBYL:在操作前就做充分的检查,例如:
boolean ret=输入密码();
if(!ret){
处理输入密码错误;
return;
}
ret=选择功能();
if(!ret){
处理选择功能错误;
return;
}
.........
缺陷:正常流程和错误处理流程代码混在一起,代码整体显得比较混乱。
★EAFP:先操作,遇到问题在处理,例如:
try{
输入密码;
选择功能;
.......
}catch(输入密码异常){
处理密码异常;
}catch(选择功能异常){
处理功能异常;
}.......
在Java中,异常处理主要的五个关键字:throw,try,catch,final,throws.
2.异常的抛出
在Java中,借助throw关键字,跑出一个指定的异常对象,将错误信息告知给调用者,具体语法:
throw newXXXException(“异常产生的原因”);
例如:
throw newArrayindexOutOfBoundsException(“传递的数组下标越界”);
注意:
1.throw必须写在方法体内部。
2. 抛出的对象必须是Exception 或者 Exception 的子类对象。
3.如果抛出的是RunTimeException或者RunTimeException的子类,则可以不用处理,直接交给JVM来处理。
4.如果抛出的是编译时异常,用户必须处理,否则无法通过编译。
5.异常一旦抛出,其后的代码就不会执行。
3、异常的捕获
异常的捕获,也就是异常的具体处理方式,主要有两种:异常声明throws以及try-catch捕获处理。
◆ 异常声明throws
处在方法声明时参数列表之后,当方法中抛出编译时异常,用户不想处理该异常,此时就可以借助throws将异常抛给方法的调用者来处理。即当前方法不处理异常,提醒方法的调用者处理异常。
语法格式:
修饰符 返回值类型 方法名(参数列表)throws异常类型1,异常类型2...{
}
需求:加载指定的配置文件config.ini
注意:
▲throws必须在方法的参数列表之后。
▲声明的异常必须是Exception或者Exception的子类。
▲方法内部如果抛出了多个异常,throws之后必须跟多个异常类型,之间用逗号隔开,如果抛出多个异常类型具有父子关系,直接声明父类即可。
▲调用声明抛出异常的方法时,调用者必须对该异常进行处理,或者继续使用throws抛出。
◆try-catch捕获并处理
throws对异常并没有真正处理,而是将异常报告给抛出异常方法的调用者,如果真正要对异常进行处理,就需要try-catch。
语法格式:
try{
//将可能出现异常的代码放在这里
}catch(要捕获的异常类型 e){
// 如果try中的代码抛出异常了,此处catch捕获时异常类型与try中抛出的异常类型一致时,或者是try中抛出异常的基类时,就会被捕获到
//对异常就可以正常处理,处理完成后,跳出try-catch结构,继续执行后序代码
//try中可能会抛出多个不同的异常对象,则必须使用多个catch来捕获
}[catch(异常类型 e){
//对异常进行处理
}finally{
//此处代码一定会被执行到
}]
★[]中表示可选项,可以添加,也可以不用添加。
★try中的代码可能会抛出异常,也可能不会。try块内抛出的异常位置之后的代码将不会被执行。
★如果异常之间具有父子关系,一定是子类异常在前catch,父类异常在后catch。
★可以通过Exception类是所有异常类的父类,因此可以用这个类型表示捕捉所以异常(不推荐)
◆finally
有些特定的代码,不论程序是否发生异常,都需要执行,比如程序中打开的资源:网络连接、数据库连接、IO流等,在程序正常或者异常退出时,必须要对资源进进行回收。另外,因为异常会引发程序的跳转,可能导致有些语句执行不到,finally就是用来解决这个问题的。
finally中的代码一定会执行的,一般在finally中进行一些资源清理的扫尾工作。
语法格式:
try{
//可能会发生异常的代码
}catch(异常类型 e){
//对捕获到的异常进行处理
}finally{
//此处的语句无论是否发生异常,都会被执行到
}
//如果没有抛出异常,或者异常被捕获处理了,这里的代码也会执行
4、异常的处理流程
◇程序先执行 try中的代码。
◇如果 try中的代码出现异常,就会结束tr中的代码,看和catch中的异常类型是否匹配。
◇如果找到匹配的异常类型,就会执行catch中的代码。
◇如果没有找到匹配的异常类型,就会将异常向上传递到上层调用者。
◇无论是否找到匹配的异常类型,finally中的代码都会被执行到(在该方法结束之前执行).·如果上层调用者也没有处理的了异常,就继续向上传递。
◇一直到main方法也没有合适的代码处理异常,就会交给JVM来进行处理,此时程序就会异常终止。