异常

:::tips

概述

  • 异常就是程序出现不正常的情况
  • 程序在执行过程中,出现的非正常的情况,最终会导致JVM非正常停止
  • java有一套独立的异常处理机制,在遇到异常时,程序会抛出一个封装了错误信息的异常对象

image.png :::

异常的处理

:::tips

JVM默认处理方案

  • 如果程序出现问题且没有任何处理,最终JVM会默认处理
    • 程序停止执行
    • 把异常的名称,异常原因及异常出现的位置等信息输出在控制台 :::

try…catch捕捉异常

:::tips

概述

  • 为了提高程序的健壮性,通常需要对异常进行捕捉和处理

格式

  1. try {
  2. 可能出现异常的代码;
  3. } catch(异常类名 变量名) {
  4. 异常的处理代码;
  5. }

    执行流程

  • 一旦出现异常,try{}中的代码将停止执行,跳转到对应的catch(){}中继续执行
  • catch执行结束后,会继续执行后面的代码

    使用注意

  • try中没遇到问题不会执行catch中的代码

  • try中遇到问题会中断执行跳转到catch中的代码
  • 没有捕获的异常会抛给上层调用者,如果没有捕捉处理会传给虚拟机导致程序停止
  • 多个catch的异常不能相同
  • 若catch中多个异常之间有字符类异常的关系,那么子类异常要在上面的catch处理,父类异常在下面的catch处理
  • 如果出现异常,只会执行一个catch

小结

  • 捕获并处理可能出现的异常
  • 好处:能让代码继续往下运行 :::

Trowable

:::tips

Throwable中提供了查看异常信息的常用方法:

  • public void printStackTrace()把异常的详细信息显示在控制台。
  • public String getMessage()返回此异常的简单描述信息
  • public String toString()返回此异常的类型和简单描述信息 :::

finally代码块

:::tips

概述:

  • 因为异常会引发程序跳转,导致某些语句执行不到,而有一些特定的代码无论异常是否发生都需要执行。
  • finally代码块就可以解决这个问题,在finally代码块中的代码一定会被执行。
  1. try{
  2. //可能出现异常的代码
  3. }catch(异常类名 变量名){
  4. //处理异常的代码
  5. }finally{
  6. //必须执行的代码
  7. //(数据库连接的关闭,IO流关闭,锁的释放)
  8. }


说明

  • 不管是否发生异常,finally代码块都会被执行
  • 因此可以在finally代码块中执行关闭连接、关闭文件和释放线程锁的操作 :::

异常处理-throws

:::tips

概述

  • 当一个方法内部产生异常,而方法无法做出处理时,可以在该方法的头部声明这个异常,把异常交给调用者进行处理。(相当于上报异常,做免责声明)

格式

  • 修饰符 返回值类型 方法名(参数列表) throws 异常类名1,异常类名2{ }
  • 注意:throws关键字可以声明抛出多个异常,多个异常使用逗号隔开。

使用场景

  • 当前方法不知道如何处理这种类型的异常,该异常应该由上一级调用者处理,如果调用者也不知道如何处理,那就继续向上声明抛出异常,以此类推直到main方法
  • 如果 main 方法也不知道如何处理这种类型的异常,也可以使用 throws 声明抛出异常,该异常将交给 JVM 进行默认处理

方法重写时的注意

  • 当进行方法重写时,子类重写的方法throws的异常的范围不能大于父类方法的异常范围
  • 父类方法没有声明抛出编译时异常,子类重写的方法也不能抛出编译时异常,只能捕捉
  • 建议重写的方法声明的异常和父类方法保持相同即可

结论

  • 对可能出现异常的方法进行异常声明
  • 告知调用者某个方法可能有问题,方法自身没有进行处理,而是让调用者去处理。 :::

throw关键字

:::tips

概述

  • Java中提供了throw关键字,可以在程序运行过程中,抛出某种特定的异常

    格式

  • throw new 异常类名();

    注意

  • throw异常以后,后面的代码将停止执行。

    意义

  • 在方法中,当传递的参数有误,程序没有运行下去的意义时,可以直接抛出异常,结束方法

  • 告知调用者方法中出现了问题,让调用者修改代码逻辑 :::

    throw与throws的区别

    :::tips

    throws

  • 是异常的处理方式之一,在方法定义时进行声明

  • 表示声明异常,告知调用者,该方法有可能会出现这样的异常

throw

  • 是产生一个异常的关键字,用在方法体内部
  • 表示创建并抛出一个异常对象,throw与return有一样的效果,执行了throw之后,方法调用会结束 :::

自定义异常

:::tips

概述

  • JDK提供的异常虽然比较多,但是不一定符合我们的需求
  • 此时我们可以根据自己的业务来定义异常类。例如年龄负数问题,考试成绩负数问题

步骤

  1. 定义异常类
  2. 写继承关系
  3. 空参构造
  4. 带参构造

存在意义

  • 就是为了让控制台的报错信息更加的见名之意。 :::

    1. public static void main(String[] args) {
    2. try {
    3. /*int arr[] = null;
    4. System.out.println(arr.length);*/
    5. SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
    6. Date parse = format.parse("2000-07-06");
    7. System.out.println(parse);
    8. //System.out.println(10/0);
    9. }catch (NullPointerException e) {
    10. System.out.println("空指针异常");
    11. }catch (ParseException e) {
    12. System.out.println("解析异常");
    13. }catch (Exception e) {
    14. System.out.println("未知异常");
    15. }
    16. }
    1. public static void main(String[] args) {
    2. try {
    3. int[] arr = new int[0];
    4. System.out.println(arr[1]);
    5. }catch (Exception e) {
    6. //把异常详细信息写到控制台上,便于程序员修改
    7. e.printStackTrace();
    8. //返回此异常的简单描述信息
    9. System.out.println(e.getMessage());
    10. //返回此类异常的类型和简单的描述信息
    11. System.out.println(e.toString());
    12. //System.out.println(toString);
    13. }
    14. }
    1. public static void main(String[] args) {
    2. Scanner sc = new Scanner(System.in);
    3. System.out.println("请输入日期(yyyy-MM-dd)");
    4. String str = sc.next();
    5. try {
    6. date(str);
    7. }catch (ParseException e) {
    8. System.out.println("输入错误");
    9. }
    10. }
    11. public static void date(String str) throws ParseException {
    12. SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
    13. Date parse = format.parse(str);
    14. System.out.println(parse);
    15. }

    ```java public static void main(String[] args) { Student stu = new Student(); Scanner sc = new Scanner(System.in); System.out.println(“请输入年龄:”); int age = sc.nextInt(); stu.setAge(age); System.out.println(stu.getAge()); }

class Student { private int age;

  1. public void setAge(int age) {
  2. if (age >= 0 && age <= 150) {
  3. this.age = age;
  4. } else {
  5. throw new RuntimeException("输入错误");
  6. }
  7. }
  8. public int getAge() {
  9. return age;
  10. }

}

```java
//自定义编译时异常
public class WrongAgeException extends Exception{
    public WrongAgeException() {
    }

    public WrongAgeException(String message) {
        super(message);
    }
}

//自定义运行时异常
public class WrongAgeException02 extends RuntimeException{
    public WrongAgeException02() {
    }

    public WrongAgeException02(String message) {
        super(message);
    }
}

 private int age;
//调用自定义编译异常
public void setAge1(int age) throws WrongAgeException {
    if (age >= 0 && age <= 150) {
        this.age = age;
    } else {
        throw new WrongAgeException("年龄异常");
    }
}
//调用自定义运行异常
public void setAge2(int age) {
    if (age >= 0 && age <= 150) {
        this.age = age;
    } else {
        throw new WrongAgeException02("年龄异常");
    }
}