:::info

一、异常体系

:::

  1. 异常体系
  • 程序在执行过程中,可能会发生各种各样的不正常情况,因此就需要很多的“异常类”来封装和描述这些不正常的情况,我们对这个“异常类”进行向上提取,就得到了异常的体系
  1. 异常体系的概述:
  • 所有不正常情况的老祖宗类为 Throwable类,在Throwable类中又有Error(错误)和Exception(异常)两个重要的子类
  1. Error (错误)类,指的就是“资源耗尽错误”或“虚拟机内部错误”等问题。如果开发中遇到了这类错误,我们在不结束程序的前提下是无法解决的。只能修改代码或重新安装虚拟机后,再运行程序
  2. Exception (异常) 类,值得就是开发中遇到的异常,这个需要开发者尽力去解决,因为异常是可以解决的不正常情况 :::info

    二、异常的分类

    :::

  3. 异常有那些分类?

  • 编译时异常:RuntimeException类及其所有子类。强制我们处理
  • 运行时异常:Exception类及其所有子类。不强制我们处理
  1. 声明异常的处理方式:throws
  • 声明异常是“消极”的处理方式,本质上没有解决异常
  1. 捕捉异常的处理方式: try…catch…finally
  • 捕捉异常属于“积极”的处理方式,从根本上已经处理了异常
  1. 关于不正常情况的分类:
  • 不可检查异常 UnCheckedException

    —->运行时异常和Error,程序在编译时期,无法检查到程序中(运行中)出现的不正常情况

  • 可检查异常 CheckedException

    —->程序在编译时期,可以检查出程序中出现的不正常情况 :::info

    三、声明异常 throws

    :::

  1. 我们需要处理哪些异常?
  • 编译时**的异常我们必须处理,否则会发生编译错误,运行时的异常我们可以处理,也可以选择不处理**

    —->这是在编译时,对代码异常的处理,这个时候代码还没有运行。


  • 无论出现那种异常,我们最终都必须处理,否则最后异常会被抛给虚拟机,造成程序的终止。

    —->这在代码运行时,无论什么异常,如果不处理,都会造成程序的终止

  1. 如何声明异常呢?
  • 当方法体中可能出现异常,此时我们又无法处理该异常,就可以把方法中出现的异常声明出来,也就是在方法声明的末尾把方法中可能出现的异常使用**throws关键字**声明出来,然后报告给方法的调用者,交给方法的调用者来处理
  1. 声明异常的语法:
  • 使用“声明异常”时,我们可以在throws 关键字末尾 声明多个“异常类”
    1. [修饰符] 返回值类型 方法名(形参列表) throws 异常类1, 异常类2, 异常类3, ... {
    2. // 方法体
    3. return [返回值];
    4. }
    注意**:“声明异常”属于消极的处理方式,本质上并没有解决方法体中可能出现的异常。只是把异常声明出来,报告给方法的上层调用者,交给方法的调用者来处理。** :::info

    四、throw和throws的区别

    ::: 面试题:请问throw和throws有什么区别?
  1. 使用位置区别
  • throw:必须在“方法体”使用
  • throws:必须在“方法声明末尾”使用
  1. 操作内容区别
  • throw:操作的是“异常对象”,只能操作“一个”异常对象
  • throws:操作的是“异常类”,可以操作“多个”异常类
  1. 本质上的区别:
  • throw: 抛出异常,一旦执行了throw概念句子,一定会抛出一个异常
  • throws:声明异常,方法末尾使用了throws关键字,方法体中未必会抛出异常

    1. public class Test02 {
    2. // 根据索引获得元素值
    3. public static int getValue(int[] arr, int index)
    4. throws NullPointerException, ArrayIndexOutOfBoundsException {
    5. // 处理arr取值为null的情况
    6. if (arr == null) {
    7. throw new NullPointerException("空指针异常,arr:" + arr);
    8. }
    9. // 处理index取值不合法的情况
    10. if (index < 0 || index >= arr.length) {
    11. // 需求:如果index取值不合法,则抛出数组索引越界异常!
    12. throw new ArrayIndexOutOfBoundsException("数组索引越界异常,index:" + index);
    13. }
    14. // 执行到此处,则证明index取值合法
    15. int value = arr[index];
    16. return value;
    17. }
    18. public static void main(String[] args)
    19. throws StudentAgeOutOfBoundsException {
    20. // 注意:在此处,我们就可以处理该异常,但是“捕捉异常”还未学习,因此暂时使用“声明异常”来处理
    21. Student stu = new Student("卧龙", -18);
    22. System.out.println(stu);
    23. }
    24. }
    25. //输出:
    26. Exception in thread "main" com.bjpowernode.p2.exception.StudentAgeOutOfBoundsException: 学生年龄越界异常,age:-18
    27. at com.bjpowernode.p2.exception.Student.setAge(Student.java:33)
    28. at com.bjpowernode.p2.exception.Student.<init>(Student.java:13)
    29. at com.bjpowernode.p2.exception.Test02.main(Test02.java:44)

    :::info

    五、捕捉异常 try…catch…finally

    :::

  1. 我们需要处理哪些异常?
  • 编译时**的异常我们必须处理,否则会发生编译错误,运行时的异常我们可以处理,也可以选择不处理**

    —->这是在编译时,对代码异常的处理,这个时候代码还没有运行。

  1. 什么是捕捉异常?
  • 捕捉异常的特点:捕捉异常属于“积极”的处理方式,本质上已经解决了异常的情况
  • 使用情况:如果方法体中可能出现异常,此时我们又能解决该异常,就使用捕捉异常来解决
  1. 捕捉异常的多种组合
  • try…catch组合:

    1. try {
    2. // 书写可能出现异常的代码
    3. }
    4. catch (异常类 对象) {
    5. // 用于处理捕获到的异常
    6. }
  • try…多catch组合:这个语法可以对代码块中出现的异常做出“针对性”的处理。**使用时,子类异常catch必须放在父类异常的catch前面**

    1. try {
    2. * // 书写可能出现异常的代码
    3. * }
    4. * catch (异常类1 对象) {
    5. * // 用于处理捕获到的异常
    6. * }
    7. * catch (异常类2 对象) {
    8. * // 用于处理捕获到的异常
    9. * }
    10. * ......更多的catch(){}
  • try…多catch…finally组合:在这个语法中,即使在try或catch中执行了return操作,finally代码块中的代码还是会执行。**在开发中,经常在finally代码块中执行“关闭资源的操作”**,例如:关闭IO流、关闭数据库连接等等操作。

    1. try {
    2. * // 书写可能出现异常的代码
    3. * }
    4. * catch (异常类1 对象) {
    5. * // 用于处理捕获到的异常
    6. * }
    7. * catch (异常类2 对象) {
    8. * // 用于处理捕获到的异常
    9. * }
    10. * ......
    11. * finally {
    12. * // 无论try中是否发生异常,则都会执行finally中的代码!
    13. * }