一.异常的概念
1.概念:
在Java中,将程序执行过程中发生的不正常行为称为异常
Java中不同类型的异常,都有与其相对应的类来描述
2.常见的异常:
2.1 算数异常
2.2 数组越界异常
2.3 空指针异常
3.异常的体系结构
1.Throwable:异常体系的顶层类,派生出两个重要的子类,Error和Exception
2.Error:指的是虚拟机无法解决的严重问题,比如:JVM的内部错误,资源耗尽等,代表为StackOverflowError和OutOfMemoryError
3.Exception:异常产生后,程序员可以通过代码处理使程序继续执行
4.异常的分类
4.1 编译时异常
在程序编译期间发生的异常,称为编译时异常,也成为受检查异常(Checked Exception)
4.2 运行时异常
程序执行期间发生的异常,称为运行时异常,也称为非受检查异常(Unchecked Exception)
RunTimeException以及其子类对应的异常,都称为运行时异常。
注意:编译时的语法错误,不能称为异常
二.异常的处理
1.防御式编程
1.1 LBYL: Look Before You Leap. 在操作之前就做充分的检查. 即:事前防御型
例如:
1.2 EAFP: It's Easier to Ask Forgiveness than Permission. "事后获取原谅比事前获取许可更容易". 也就是先操作, 遇到问题再处理. 即:事后认错型
正常流程和错误流程是分离开的, 程序员更关注正常流程,代码更清晰
例如:
2.异常的抛出
在Java中,可以借助throw关键字,抛出一个指定的异常对象,将错误信息告知调用者
throw new XXXException("异常产生的原因");
例如:
注意:
1.throw必须写在方法体内部
2.抛出的对象必须时Exception或者Exception的子类对象
3.如果抛出的是RunTimeException 或者 RunTimeException 的子类,可以不用处理,交给JVM处理
4.如果是编译时异常,用户必须处理,否则无法通过编译
5.异常一旦抛出,其后代码不执行
3.异常的捕获
3.1 异常申明throws
当方法中抛出编译时异常,用户不想处理该异常,此时就可以借助throws将异常抛给方法的调用者来处理。即当前方法不处理异常,提醒方法的调用者处理异常
语法格式:
修饰符 返回值类型 方法名(参数列表) throws 异常类型1,异常类型2...{
}
注意:
1.throws必须跟在方法参数之后
2.申明的异常必须是Exception或者Exception的子类
3.方法内部如果抛出了多个异常,throws之后必须跟着多个异常类型,之间用逗号隔开,如果具有父子关系,直接声明父类
4.调用声明抛出异常的方法时,调用者必须对该异常进行处理,或者继续用throws抛出
3.2 try - catch捕获处理
语法格式:
try{
// 将可能出现异常的代码放在这里
}catch(要捕获的异常类型 e){
// 如果try中的代码抛出异常了,此处catch捕获时异常类型与try中抛出的异常类型一致时,或者是try中抛出异常的基类时,就会被捕获到
// 对异常就可以正常处理,处理完成后,跳出try-catch结构,继续执行后序代码
}catch(异常类型 e){
// 对异常进行处理
}finally{
// 此处代码一定会被执行到
}
注意事项:
1. try块内抛出异常位置之后的代码将不会被执行
2. 如果抛出异常类型与catch时异常类型不匹配,即异常不会被成功捕获,也就不会被处理,继续往外抛,直到JVM收到后中断程序----异常是按照类型来捕获的
3. try中可能会抛出多个不同的异常对象,则必须用多个catch来捕获----即多种异常,多次捕获
4.如果异常之间具有父子关系,一定是子类异常在前catch,父类异常在后catch,否则语法错误
5.finally中的代码无论前面是否遇到异常都会呗被执行
三.异常处理流程总结
1.程序先执行try中的代码
2.如果try中的代码出现异常,就会结束try中的代码,查看和catch中类型是否匹配
3.如果找到匹配的异常类型,执行catch中代码
4.如果没有找到匹配的异常类型,就会将异常向上传递到上层调用者
5.无论有没有找到匹配的异常类型,finally中代码必然被执行
6.如果上层调用者也没有处理了的异常,将会继续向上传递
7.一直到main方法也没有合适的代码异常,就会交给JVM处理,程序终止运行
四.自定义异常类
自定义的异常类要继承Exception或RunTimeException
例如:
class UserNameException extends Exception {
public UserNameException(String message) {
super(message);
}
}
注意:
1.继承Exception默认时受查异常
2.继承RunTimeException默认时非受查异常