1. 异常
掌握:
1. 什么是异常
就是程序在编译或运行过程中,发生的错误;
2. 异常分类
运行时异常
程序在运行过程中,有可能发生错误;
编译时异常
程序在编译过程中,必须处理的错误;
3. 【如何处理异常】
抛出 throws 在方法声明上,抛出一个异常给调用者
捕获 try...catch...finally 把有问题的代码捕获,自己处理
异常就是程序在编译或运行过程中,发生的错误;
错误分类:
有些错误是可以弥补; Exception
但是有些错误,无法弥补,只能修改代码; Error
StackOverflowError 栈内存错误
OutOfMemoryError 内存溢出错误
- Throwable
- Error 错误(只能修改代码,别无他法) StackOverflowError
- Exception 异常(两种处理方式:抛出,捕获)
- 【运行时异常】:继承RuntimeException的异常
在程序运行过程中,有可能发生错误
- 【编译时异常】:继承Exception的异常
在程序编译过程中,必须处理的错误
见过的异常:
运行时异常:在程序运行过程中,有可能发生错误
NullpointerException 空指针异常
IndexOutOfBoundsException 索引越界异常
- StringIndexOutOfBoundsException 字符串索引越界异常
- ArrayIndexOutOfBoundsException 数组索引越界异常
ClassCastException 类型转换异常
NumberFormatException 数字格式化异常
ConcurrentModificationException 并发修改异常
UnsupportedOperationException 不支持操作异常 List.of();
NoSuchElementException 找不到元素异常
编译时异常:在程序编译过程中,必须处理的错误
ParseException 解析异常
JVM异常处理方式:
1. 如果我们没有主动写代码抛出异常,那么如果代码错了,JVM就会在底层帮我们new一个对应的异常对象出来,抛给调用者处理;
2. 如果调用者没有对应的处理方式,那么继续往它的调用者抛,最后一直没有处理方式,那么JVM负责兜底。
3. JVM接受到了异常对象,直接将程序停止,将异常对象的信息,输出在控制台;
备注:最后被JVM处理的异常,在后期,我们称之为BUG,还是由程序员处理;
throw: 【制造一个异常】
在方法中,制造一个异常;
不是遇到了判断就用,程序是要避免异常,而不是动不动就制造异常;
除非是有业务需求,我们才会自己制造一个异常;
int getValue(int[] arr , int index){arr ={0,0,0};
if(arr == null) {
throw new NullPointerException("数组为null");
}
if(index <0||index >=arr.length) {
throw new NullPointerException("索引越界了");
}
}
throws:【抛出异常】
运行时异常: 可以不抛出 普通影响不大的病。你告诉别人,你感冒了。
编译时异常: 必须抛出 需要别人注意的传染病。
Throwable:
常用方法:
1. getMessage(); 获取异常简短信息(异常原因);
2. toString(); 获取异常类和异常原因; 包含异常类,和异常的具体原因
3. printStackTrace(); 打印异常详细信息; 包含异常类,异常原因,异常位置(类和方法名、行号)
finally: 关键字
1. 只能同try...catch...finally一同使用;
2. 通常用来释放资源
3. 一定不要在finally里面写return;因为一旦写了return那么返回的结果,一定是finally中的结果;
面试题:
final和finally、finalize三者有联系吗? 他们分别是什么?
三者没有一毛钱关系;
final:修饰符 用来修饰类,方法,变量,表示最终的意思;
finally:try...catch...finally的语句块,不能单独使用,通常用来释放资源
finalize:是Object类中的方法,被垃圾回收器自动调用,通常用来做一个对象被回收之前最后的遗言;
异常处理的三种方式:
1. 多个异常,多个try...catch
能够处理所有异常,并针对每一个异常进行处理,但是不常用,麻烦。
2. 多个异常,一个try多个catch
这个一次只能处理一个异常;
3. 多个异常,一个try一个catch 【常用】
针对上面的处理方式来说,上面的处理方式,可以针对每个异常做针对性的处理,但是这个不行;只能同一处理;
1. 多个异常,多个try...catch
try{
大儿子
}catch(大儿子 e){
//打一顿
}
try{
小儿子
}catch(小儿子 e){
//打断腿
}
try{
小女儿
}catch(小女儿 e){
//以后别这样了
}
2. 多个异常,一个try多个catch
try{
大儿子
小儿子
小女儿
}catch(小儿子 e){
//打一顿
}catch(大儿子 e){
//打断腿
}catch(小女儿 e){
//以后别这样了
}
3. 多个异常,一个try一个catch
try{
大儿子 s.toString()
小儿子 上传文件
小女儿 下载文件
}catch(老子 e){
//我来处理,同一处理 记录日志
}
异常注意事项:【了解】
1. 父类方法中,如果没有抛异常,那么子类重写方法,也不能抛异常,只能try...catch处理
2. 父类方法中,如果抛出异常,那么子类重写的方法,也可以抛【小于等于】父类的异常
自定义异常:【了解】
自定义编译时异常:继承Exception或者非RuntimeException的子类
自定义运行时异常:继承RuntimeException
然后定义两个构造方法即可;