# 第四章 异常

# 4.1 异常处理入门

public class Test {
    public static void main(String[] args) {
        int num1 = 10;
        int num2 = 0;
        /*
            当执行 num1 / num2 时,因为分母为 0 会导致程序抛出异常导致程序崩溃,这样以后的代码就不继续执行了
            当然不应该出现一个不致命的问题就导致程序崩溃
            这时就需要提供一个异常处理机制来解决问题
            如果认为一段代码可能出现异常或者问题,可以使用异常处理机制来解决,从而保证程序的健壮性
            如果进行异常处理,那么即使出现了异常,程序也是可以继续执行
        */
        try {
            int res = num1 / num2;
        } catch (Exception e) {
            //throw new RuntimeException(e);
            System.out.println("异常信息是: " + e.getMessage()); //异常信息是: / by zero
        }

        System.out.println("程序继续进行...");
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# 4.2 异常基本介绍

  1. Java 语言中,将程序执行中发生的不正常情况称为异常。(开发过程中的语法错误和逻辑错误不是异常)

  2. 执行过程中所发生的异常事件可分为两大类:

(1)Error(错误):Java 虚拟机无法解决的严重问题,如:JVM 系统内部错误、资源耗尽等严重情况。比如:StackOverflowError[栈溢出] 和 OOM[out of memory],Error 是严重错误,程序会崩溃。

(2)Exception:其它因编程错误或偶然的外在因素导致的一般性问题,可以使用针对性的代码进行处理。例如空指针访问,试图读取不存在的文件,网络连接中断等等,Exception 分为两大类:运行时异常[程序运行时发生的异常] 和 编译时异常[编程时编译器检查出的异常]

# 4.3 异常体系图

  1. 异常分为两大类,运行时异常和编译时异常

  2. 运行时异常编译器检查不出来,一般是指编程时的逻辑错误,是程序员应该避免其出现的异常,java.lang.RuntimeException 类及它的子类都是运行时异常

  3. 对于运行时异常可以不作处理,因为这种异常很普遍,若全处理可能会对程序的可读性和运行效率产生影响

  4. 编译时异常是编译器要求必须处置的异常

# 4.4 运行时异常

常见的运行时异常包括:

  1. NullPointerException 空指针异常

  2. ArithmeticException 数学运算异常

  3. ArrayIndexOutOfBoundsException 数组下标越界异常

  4. ClassCastException 类型转换异常

  5. NumberFormatException 数字格式不正确异常

# 4.4.1 运行时异常举例

  1. NullPointerException 空指针异常:当应用程序试图在需要对象的地方使用 null 时,抛出该异常
public class NullPointerException {
    public static void main(String[] args) {
        String name = null;
        System.out.println(name.length());
    }
}
1
2
3
4
5
6

  1. ArithmeticException 数学运算异常:当出现异常的运算条件时,抛出此异常。例如:一个整数除以零时,抛出此类的一个实例
public class ArithmeticException {
    public static void main(String[] args) {
        int num1 = 10;
        int num2 = 0;
        int sum = num1 / num2;
        System.out.println(sum);
    }
}
1
2
3
4
5
6
7
8

  1. ArrayIndexOutOfBoundsException 数组下标越界异常:用非法索引访问数组时抛出的异常,如果索引为负或大于等于数组大小,则该索引为非法索引
public class ArrayIndexOutOfBoundsException {
    public static void main(String[] args) {
        int[] arr = {1, 2, 4};
        for (int i = 0; i <= arr.length; i++) {
            System.out.println(arr[i]);
        }
    }
}
1
2
3
4
5
6
7
8

  1. ClassCastException 类型转换异常:当试图将对象强制转换为不是实例的子类时,抛出该异常。
public class ClassCastException {
    public static void main(String[] args) {
        A b = new B(); //向上转型
        B b2 = (B) b; //向下转型
        C c2 = (C) b; //错误
    }
}
class A {}
class B extends A {}
class C extends A {}
1
2
3
4
5
6
7
8
9
10

  1. NumberFormatException 数字格式不正确异常:当应用程序试图将字符串转换成一种数值类型,但该字符串不能转换为适当格式时,抛出该异常,使用异常我们可以确保输入的是满足条件数字
public class NumberFormatException {
    public static void main(String[] args) {
        String name = "张三";
        int num = Integer.parseInt(name); //不能将字符型转成 int 型
        System.out.println(num);
    }
}
1
2
3
4
5
6
7

# 4.5 编译时异常

编译异常是指在编译期间就必须处理的异常,否则代码就不能通过编译

常见的编译异常:

  1. SQLException:操作数据库时,查询表可能发生异常

  2. IOException:操作文件时,发生的异常

  3. FileNotFoundException:当操作一个不存在的文件时发生的异常

  4. ClassNotFoundException:加载类但是该类不存在时的异常

  5. EOFException:操作文件到文件末尾发生异常

  6. IllegalArguementException:参数异常

# 4.6 try-catch-finally 异常处理

try {
    代码可能有异常
} catch(Exception e) {
    捕获异常
    1.当异常发生时,系统将异常封装成 Exception 对象 e,传递给 catch
    2.得到异常对象后,程序员自己处理
    3.如果没有发生异常 catch 代码块不执行
} finally {
    不管 try 代码块是否有异常发生,始终要执行 finally
    所以通常将释放资源的代码放在 finally
}
1
2
3
4
5
6
7
8
9
10
11
  1. 如果异常发生了,则异常发生后面的代码不会执行,直接进入到 catch 块

  2. 如果异常没有发生,则顺序执行 try 的代码块,不会进入到 catch

  3. 如果希望不管是否发生异常都执行某段代码(比如关闭连接、释放资源等),则在 finally 内写下此代码

  4. 可以有多个 catch 语句,捕获不同的异常(进行不同的业务逻辑),要求父类异常在后,子类异常在前,比如:Exception 在后,NullPointerException 在前,如果异常发生,只会匹配一个 catch

# 4.7 throws 异常处理

# 4.7.1 throws 处理机制图

# 4.7.2 throws 异常处理基本介绍

  1. 如果一个方法中的语句执行时可能生成某种异常,但是并不确定如何处理这种异常,则此方法应显示地声明抛出异常,表明该方法将不对这些异常进行处理,而由该方法的调用者负责处理

  2. 在方法声明中用 throws 语句可以声明抛出异常的列表,throws 后面的异常类型可以是方法中产生的异常类型,也可以是它的父类

# 4.7.3 throws 异常处理注意事项和细节

  1. 对于编译异常,程序中必须处理

  2. 对于运行时异常,程序中如果没有处理,默认就是 throws 的方式处理

  3. 子类重写父类的方法时,对抛出异常的规定:子类重写的方法所抛出的异常类型要么和父类抛出的异常一致,要么为父类抛出的异常的类型的子类型

  4. 在 throws 过程中,如果有方法 try-catch,就相当于处理异常,就可以不必 throws

# 4.8 自定义异常

  1. 定义类:自定义异常类名(程序员自己写)继承 Exception 或 RuntimeException

  2. 如果继承 Exception,属于编译异常

  3. 如果继承 RuntimeException,属于运行异常(一般来说继承 RuntimeException)

//自定义一个异常
class AgeException extends RuntimeException {
    public AgeException(String message) {
        super(message);
    }
}

public class CustomException {
    public static void main(String[] args) {
        int age = 150;
        //要求范围在 18-120 之间,否则抛出一个自定义异常
        if (!(age >= 18 && age <= 120)) {
            throw new AgeException("年龄需要在 18-120 之间");
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 4.9 throws 和 throw 的区别

意义 位置 后面跟的东西
throws 异常处理的一种方式 方法声明处 异常类型
throw 手动生成异常对象的关键字 方法体中 异常对象
最近更新: 3/24/2025, 2:07:09 PM
开发笔记   |