异常的处理方法

一、Java的异常处理机制:

在 Java的异常处理机制为:抛出异常,捕捉异常。

  1. 抛出异常:方法中出现异常时,方法会创建对应的异常对象并交付运行时系统,这个异常对象中包含了异常类型和各种异常出现时的异常信息。运行时系统则主要负责寻找处置异常的代码并执行。
  2. 捕获异常:在方法抛出异常之后,运行时系统将转为寻找合适的异常处理器(exception handler)。潜在的异常处理器是异常发生时依次存留在调用栈中的方法的集合。当异常处理器所能处理的异常类型与方法抛出的异常类型相符时,即为合适 的异常处理器。运行时系统从发生异常的方法开始,依次回查调用栈中的方法,直至找到含有合适异常处理器的方法并执行。当运行时系统遍历调用栈而未找到合适 的异常处理器,则运行时系统终止。同时,意味着Java程序的终止。

一个方法所能捕捉的异常,一定是Java代码在某处所抛出的异常。简单地说,异常总是先被抛出,后被捕捉的。

Java规定,对于可查异常必须捕捉、或者声明抛出。允许忽略不可查的RuntimeExceptionError

以上内容引用自: 异常处理的机制

二、 try - catch - finally :

利用 try-catch-finally 可以捕获及处理异常,其语法格式如下:

try{
    //尝试运行的代码
}catch(异常类型 | 异常的变量名){
    //异常处理代码
}finally{
    //必定会执行的代码
  • try{}语句块:try{}内是要尝试运行的代码,是受异常监控的区域,发生异常会抛出相应的异常对象。
  • catch(异常类型 | 异常的变量名){}语句块:

    • try{}中发生异常,就要到catch中找对应的异常类,并执行相应的执行代码。如果catch(){}中没找到,异常会从try语句块中抛出,让外层处理。
    • catch(){}语句块是带参数的,就是可捕获的异常类型,如catch(Exception e)
    • catch语句可以有多个,但catch 的范围只能从低到高(子类到父类),只要出现父类,下面的catch语句就不能再出现其子类,如出现Exception后就不能出现Exception的子类:

      //编译通过,后面的catch类型不能比上一个catch类型低
      try {
          System.out.println(a/b);
      } catch (ArithmeticException e) {
          System.out.println("被除数不能为0");
      } catch (NullPointerException e) {
          System.out.println("NullPointerException");
      } catch (Exception e){
          System.out.println("Exception");
      } catch (Error e){
          System.out.println("Error");
      } catch (Throwable t){
          System.out.println("Throwable");
      } finally {
          System.out.println("最后处理");
      }
      
      //编译不通过,报错 ArithmeticException 是 Exception 子类
      try {
          System.out.println(a/b);
      } catch (Exception e) {
          System.out.println("Exception");
      } catch (ArithmeticException e){
          System.out.println("ArithmeticException");
      } finally {
          System.out.println("最后处理");
      }
      当catch 命中相应的异常类型,就会执行相应的异常处理代码,并跳过后面的catch语句,直接走finally语句。
  • 只要有finally{}语句块,只要程序不被强行终止,里面的代码就一定会被执行。即便出现 break, return等流程控制语句也一样要执行finally语句。

    ​```java
    package com.zctou.exception;
    public class Demo01 {
        public static void main(String[] args) {
            int a = 1;
            int b = 0;
            try {
                System.out.println(a/b);
            } catch (ArithmeticException e) {
                System.out.println("被除数不能为0");
            } finally {
                System.out.println("最后处理");
            }
        }
    }
    //输出:
    被除数不能为0
    最后处理
    finally 不管前面的异常怎么样都会执行,多用于处理善后的事宜,如关闭数据库,关闭文件读取IO流等。
  • try就必须至少要有一个catch()finally语句块。

三、异常抛出 throw 和 throws

抛出异常:异常把异常对象通过向调用层抛出,一层层向上抛直至传递给java虚拟机处理,称为抛出异常。

抛出异常有两种情况:一种是在方法体中主动抛出,另一种则是在方法声明时抛出异常。主动抛出异常,在方法里用关键字throw,在方法声明中用关键字throws

  • 方法体中抛出异常,关键字throw,格式如下:

    throw new 异常对象

    示例:

    package com.zctou.exception;
    
    public class Demo02 {
    
        public static void main(String[] args) {
            new Demo02().devided(1,0);
        }
        //定义除法,如果被除数为0, 主动抛 ArithmeticException 出异常
        public void devided(int a, int b) {
            if(b==0) {
               throw new ArithmeticException(); // 文体中主动抛出一个对象
            }
            System.out.println(a/b);
        }
    }
    //输出:
    Exception in thread "main" java.lang.ArithmeticException
        at com.zctou.exception.Demo02.devided(Demo02.java:11)
        at com.zctou.exception.Demo02.main(Demo02.java:6)
  • 在方法声明中抛出异常,关键字throws,格式如下:

    throws 异常类型

    示例:

    package com.zctou.exception;
    
    public class Demo03 {
    
        public static void main(String[] args) {
            try {
                new Demo03().devided(1,0);
            } catch (ArithmeticException e) {
                System.out.println("外层处理异常");
                e.printStackTrace();
            }
        }
    
        //假设这个方法内处理不了或者不想处理异常,方法声明中用`throws`抛出异常
        public void devided(int a, int b) throws ArithmeticException{
            System.out.println(a/b);
        }
    }
    //输出:
    外层处理异常
    程序不会停止
    java.lang.ArithmeticException: / by zero
        at com.zctou.exception.Demo03.devided(Demo03.java:17)
        at com.zctou.exception.Demo03.main(Demo03.java:7)
  • 不受检异常(RuntimeException):在方法内主动抛出,函数上不用重复声明抛出。
  • 若在方法声明中主动抛出异常,调用方法时,不用try-catch-finally处理。

小结:

  • throws用于对方法进行声明,如果不声明throws,那么一般的Exception都要在这个方法中处理掉,否则编译发生错误。
  • 如果方法声明了throws,可以交给上一级方法处理,但有些Exception可以不用catch捕获,编译也会通过。
文章目录