一、什么是异常
定义
异常(Throwable),是代码运行中的不符合预期的特殊情况
异常的分类及特点
1.分类
①异常可以分为错误(Error)和异常(Exception)
②错误通常是因为语法逻辑或者硬件问题导致
③异常是程序在运行和配置中产生的问题
④异常可以再细分为受检异常(编译就报错)、非受检异常(编译时不报错,运行时报错)
2.异常的必要性
在代码中存在各种各样的不可预期情况,异常可以起到维持程序的稳定性作用
二、常见的异常
1.算术异常(ArithmeticException )
通常是因为运算逻辑有误,例如0作为被除数
2.数组索引越界异常(ArrayIndexOutOfBoundsException )
通常因为使用超出数组长度的元素,例如一个数组的长度为2,然后给数组下标为3的元素赋值时就会报数组越界
3.空指针异常
调用一个空对象的方法,例如调用一个值为null的对象的quals方法与一个其他的值进行比较(所以使用equals方法比较String值的时候通常把变量写在后面的括号内,明确的值写在前面)
4.类型转换异常
例如子类强转成父类
三、解决异常
1.捕获异常
捕获异常之后的代码语句正常运行,捕获异常通常用在自己能解决异常,并且需要后续代码正常运行的情况下
/*
语法格式
try{
可能出现异常的代码
}catch(异常类型 异常名){
处理代码
}
*/
int[] nums=new int[2];
try{
nums[3]=15;//超出数组定义长度,属于数组索引越界()
}catch(ArrayIndexOutOfBoundsException e){
System.err.println("数组索引异常")//err设定输出字体颜色为红色
}
System.out.println("捕获异常后")
2.当捕获多个异常时
public static void main(String[] args){
test(null);
test();
}
public static void test(String str){
try{
System.err.println(str.equals(""));//如果传入参数为null,则爆空指针异常
int num=12/0;//算术异常
System.out.println("try代码块中")
/*如果try中有多个异常,可以在catch中使用|写多个异常,不能用||,或者可以直接用Exception涵盖所有异常*/
}catch(NullPointerException | ArithmeticException e){
e.printStackTrace//输出异常信息
System.out.println("catch代码块中")
}
System.out.println("结果");
}
最后结果输出:
空指针异常报错
catch代码块中
最后
true
算术运算报错
catch代码块中
最后
步骤解析
①第一次调用方法的时候传入参数为null,try中第一行代码爆空指针异常
②由于第一行报错了,try代码块中在报错代码后的其他代码不执行,跳到catch代码块中继续执行
③第二次调用方法传入参数不为空,执行到第二行报算术异常,第三行的输出语句仍然不执行,继续跳到catch代码块中执行其他代码
由此可以得知,在捕获多个异常时,try代码块中,从出现异常的语句开始,知道try代码块结束之间的代码都不会再执行,catch代码块已经外部后面的代码不受影响
四、finally(注意不是final)
1.作用
保证finally代码块中的代码一定会被执行
2.如何使用
写在catch代码块之后,当没有catch代码块时可以直接写在try代码块之后
3.语法格式
try{
}catch(){
}finally{
}
五、声明异常类型(throws,可以一次声明多个异常类型)
1.定义
声明可能存在的异常,由上层解决,如果上层无法解决将继续向上层声明出来,直至结尾
声明异常,如果没有捕获的话,结果还是会报错停止后续代码的运行
2.作用
为了能够让上层捕获异常,如果不抛出异常,一旦程序出现错误上层不知道是哪个部位出错,只知道有一个部位出错,不知道用什么办法解决。这是如果抛出了异常,上层代码可以知道问题代码所在,及时处理避免程序崩溃
3.案例
public class Demo1{
/*3.抛出到这里无法继续向上抛出了,编译报错程序结束运行,异常代码之后的其他代码不运行,即使后面又finally代码块也不会再继续执行了*/
public static void main(String[] args)throws Exception{
//2.调用方要处理异常,如果不处理的话继续向上抛出
total(4);
//4.不会运行后续代码,程序已经被结束了
try{
int num=5/0;
}catch(ArithmeticException e){
//System.out.println("算术异常");
}finally{
System.out.println("finally输出");
}
}
//1.throws Exception将可能出现的异常向上抛出
public static double total(int num)throws Exception{
return num/0; //算术异常
}
}
六、抛出异常对象(只能抛出单个异常对象)
1.定义
在方法内通过手动创建对象抛出异常
2.语法格式
throw new 异常类型
3.案例
public static void main(String[] args) {
int num=0;
total(num);
}
public static void total(int num){
int num2=5/num;//传入参数为0时,算术异常
//throw new 异常类型();
throw new ArithmeticException("除数不能为0");
}
七、自定义异常
1.语法格式
public class (类名+Exception) extends Exception(){
//无参构造方法
public (类名+Exception)(){
super();
}
//添加一个带异常信息的有参构造方法
public (类名+Exception)(){
super();
}
}
2.注意点
- 自定义异常的类名通常末尾加上Exception表明这是异常
- 自定义异常必须要继承Exception或者RuntimeException
- 继承自Exception说明是一个编译期间就会报错的异常,编译期异常必须处理try或者throws
- 继承自RuntimeException的异常就是一个运行期异常,无需处理,交给虚拟机处理,中断处理。
- 通过向构造方法中默认存在的父类构造方法super()传入参数,输出异常信息