0


一文轻松掌握异常

轻松掌握异常

异常的背景

初始异常

除以 0

代码如下:

publicstaticvoidmain(String[] args){System.out.println(10/0);}

因为 0 不能做除数,所以会报异常:
在这里插入图片描述

数组下标越界

代码如下:

publicstaticvoidmain(String[] args){int[] arr ={1,2,3};System.out.println(arr[9]);}

因为数组的下标最大是 2 ,这里是访问下标 9 ,所以会越界。
在这里插入图片描述
上面这些都是运行时异常,我们之前还遇到过编译时异常

编译时异常

使用类克隆的时候,如果不抛出异常的话,就会报错导致出现无法完成编译:

classPersonimplementsCloneable{publicint id;}publicclassMain{publicstaticvoidmain(String[] args){Person person =newPerson();Person person1 =(Person) person.clone();}}

报异常如下:
在这里插入图片描述
如果重写克隆方法,并且抛出异常的话,程序就可以运行了。

classPersonimplementsCloneable{publicint id;@OverrideprotectedObjectclone()throwsCloneNotSupportedException{returnsuper.clone();}}publicclassMain{publicstaticvoidmain(String[] args)throwsCloneNotSupportedException{Person person =newPerson();Person person1 =(Person) person.clone();}}

这样程序就能运行了。

异常的基本用法

捕获异常

通过 try catch 来捕获并且处理异常,代码如下:

try{
    有可能出现异常的语句 ;}[catch(异常类型 异常对象){}...][finally{
    异常的出口
}]
  • try 代码块中放的是可能出现异常的代码.
  • catch 代码块中放的是出现异常后的处理行为.
  • finally 代码块中的代码用于处理善后工作, 会在最后执行.
  • 其中 catch 和 finally 都可以根据情况选择加或者不加.

异常程序的执行过程

在代码抛出异常之后,异常之后的代码就不执行了。代码如下:

publicstaticvoidmain(String[] args){int[] arr =newint[]{1,2,3};System.out.println(arr[5]);System.out.println("哈喽!!!");}

运行结果如下:
在这里插入图片描述
在运行到异常的代码之后,报出异常之后下面的代码就不执行了。

使用 try catch 处理异常的代码运行过程

代码如下:

publicstaticvoidmain(String[] args){int[] arr =newint[]{1,2,3};try{System.out.println(arr[5]);System.out.println("haha");}catch(ArrayIndexOutOfBoundsException e){System.out.println("捕捉到一个数组越界异常");}System.out.println("哈喽!!!");}

运行结果如下:
在这里插入图片描述
通过 try 来捕捉异常,然后通过 catch 来处理异常。try 捕捉到异常之后,异常下面的代码就不执行了。然后就是 catch 来执行,catch 执行完毕之后才可以继续往下执行。当然在 catch 当中也可以添加如下代码:

e.printStackTrace();

这里就是打印异常信息栈,输出异常的位置在哪里。交给 JVM 来处理异常,JVM 来处理的话,就会直接终止程序。

出现多个异常

如果出现多个异常的话,就可以使用多个 catch 来捕捉异常。代码如下:

publicstaticvoidmain(String[] args){int[] arr =newint[]{1,2,3};try{
        arr =null;System.out.println(arr[5]);System.out.println("haha");}catch(ArrayIndexOutOfBoundsException e){System.out.println("捕捉到一个数组越界异常");}catch(NullPointerException e){System.out.println("捕捉到了空指针异常");}System.out.println("哈喽!!!");}

运行结果如下:
在这里插入图片描述
当然代码也能这样简写:

publicstaticvoidmain(String[] args){int[] arr =newint[]{1,2,3};try{
        arr =null;System.out.println(arr[5]);System.out.println("haha");}catch(ArrayIndexOutOfBoundsException|NullPointerException e){System.out.println("捕捉到一个数组越界 或者 空指针异常");}System.out.println("哈喽!!!");}

运行结果如下:
在这里插入图片描述

Java 的异常体系

所有的异常都来自一个 throwable :
在这里插入图片描述
如果在 IDEA 当中查看异常的父子类关系时,就有如下关系图:
在这里插入图片描述

父类 Exception

所有的异常都来自父类 Exception ,当然也可以在 catch 的时候直接写 Exception 。但是不建议这样做,因为这样就不知道是什么异常了。
注意:catch 在捕捉异常的时候,最好是先子类,再父类。这样就可以一阶一阶的处理异常。如果是先父类再子类的话,就会报错。
在这里插入图片描述

finally

finally 一般用作资源的关闭。比如关闭 Scanner :

publicstaticvoidmain(String[] args){Scanner scanner =newScanner(System.in);int n = scanner.nextInt();try{System.out.println(10/ n);}catch(InputMismatchException e){
        e.printStackTrace();System.out.println("输入有误");}catch(ArithmeticException e){
        e.printStackTrace();System.out.println("算术异常,可能 0 做了除数");}finally{
        scanner.close();System.out.println("finally 执行了");}}

不论是否发生异常,finally 都会执行:
在这里插入图片描述
就算交给 JVM 处理,还是会执行 finally 代码如下:

publicstaticvoidmain(String[] args){Scanner scanner =newScanner(System.in);int n = scanner.nextInt();try{System.out.println(10/ n);}catch(InputMismatchException e){
        e.printStackTrace();System.out.println("输入有误");}finally{
        scanner.close();System.out.println("finally 执行了");}}

在这里插入图片描述

try catch finally的返回值

当 try 和 finally 当中都有返回的时候,结果是什么?

publicstaticintfunc3(){int a =10;try{return a;}catch(ArithmeticException e){
        e.printStackTrace();}finally{return20;}}publicstaticvoidmain(String[] args){int n =func3();System.out.println(n);}

运行结果如下:
在这里插入图片描述
因为 finally 的特点是:不管抛没抛异常,finally 都会被执行。所以本来应该返回 a 的地方,就返回了 20 。所以:** 尽量避免在 finally 当中使用 return** 。

异常处理流程

  1. 程序先执行 try 中的代码
  2. 如果 try 中的代码出现异常, 就会结束 try 中的代码, 看和 catch 中的异常类型是否匹配.
  3. 如果找到匹配的异常类型, 就会执行 catch 中的代码
  4. 如果没有找到匹配的异常类型, 就会将异常向上传递到上层调用者.
  5. 无论是否找到匹配的异常类型, finally 中的代码都会被执行到(在该方法结束之前执行).
  6. 如果上层调用者也没有处理的了异常, 就继续向上传递.
  7. 一直到 main 方法也没有合适的代码处理异常, 就会交给 JVM 来进行处理, 此时程序就会异常终止.

自定义异常

在自定义抛出异常的时候,用 throw 来抛出异常。

publicstaticvoidfunc4(int x)throwsRuntimeException{if(x ==10){System.out.println(10/ x);thrownewRuntimeException("x == 10");}}publicstaticvoidmain(String[] args){try{func4(10);}catch(ArithmeticException e){
        e.printStackTrace();}}

运行结果如下:
在这里插入图片描述

利用异常实现恢复模型

使用 while 循环建立类似 ”恢复模型“ 的异常处理行为,它将不断重复,直到异常不再抛出。

publicstaticvoidmain13(String[] args){int i =0;while(i <10){try{if(i <10){thrownewRuntimeException("x < 10");}}catch(RuntimeException e){
            e.printStackTrace();System.out.println("尝试处理异常");
            i++;}}System.out.println("异常处理结束了");}

运行结果如下:
在这里插入图片描述


本文转载自: https://blog.csdn.net/sjp151/article/details/122596991
版权归原作者 Lockey-s 所有, 如有侵权,请联系我们删除。

“一文轻松掌握异常”的评论:

还没有评论