01-异常体系

1. 异常概念

概念:程序在运行过程中出现的特殊情况
必要性:任何程序都可能存在大量的位置问题、错误;如果不对这些问题进行正确处理,则可能导致程序的中断,造成不必要的损失。
如果某个方法不能按照正常的途径完成任务,就可以通过另一种路径退出方法。在这种情况下会抛出一个封装了错误信息的对象。此时,这个方法会立刻退出同时不返回任何值。另外,调用这个方法的其他代码也无法继续执行,异常处理机制会将代码执行交给异常处理器。

2. 异常分类体系

Throwable类:可抛出的,Java中一切错误或异常的父类
位置:java.lang.Throwable;
分类:
——|–Error类:JVM、硬件、执行逻辑错误、不能手动处理。
——|–Exception类:程序在运行和配置中产生的问题,可处理。
————|–RuntimeException类:运行时异常,可处理,可不处理
————|–CheckedException类:受查异常,必须处理
程序编写时,异常不处理的话,JVM虚拟机会去自动处理(打印堆栈跟踪信息)。
image-20230316135745520
Throwable 是 Java 语言中所有错误或异常的超类。下一层分为 Error 和 Exception。

  1. Error
    指 java 运行时系统的内部错误和资源耗尽错误。应用程序不会抛出该类对象。如果出现了这样的错误,除了告知用户,剩下的就是尽力使程序安全的终止。

  2. Exception
    Exception(RuntimeException、CheckedException)
    有两个分支,一个是运行时异常 RuntimeException ,一个是受查异常CheckedException。
    RuntimeException,如 :NullPointerException 、 ClassCastException;CheckedException,如 I/O 错误导致的 IOException、SQLException。 RuntimeException 是那些可能在 Java 虚拟机正常运行期间抛出的异常的超类。
    CheckedException:一般是外部错误,这种异常都发生在编译阶段,Java 编译器会强制程序去捕获此类异常,即会出现要求你把这段可能出现异常的程序进行 try catch,该类异常一般包括几个方面:
    1)试图在文件尾部读取数据
    2)试图打开一个错误格式的 URL
    3)试图根据给定的字符串查找 class 对象,而这个字符串表示的类并不存在

如果出现 RuntimeException,那么一定是程序员的错误。

3. 异常的抛出方式:throw & throws & 默认

抛出异常有三种形式,一是 throw,一个 throws,还有一种JVM自动抛异常(即默认没有通过代码主动抛出时)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class TestException {
public static void main(String[] args) {
String s = "abc";
if ("abc".equals(s)) {
// throw用在【函数内】,后面跟异常对象
throw new NumberFormatException();
} else {
System.out.println(s);
}
}

// throws用在【函数上】,后面跟异常类,可以跟多个,分隔
public static int method(int a, int b) throws Exception,NumberFormatException {
return a / b;
}
}

image-20230316135758501

4. 异常的处理方式:try-catch-finally

catch中异常处理的代码通常采取三种方案:
方案①:自定义处理, 如println();
方案②:打印堆栈跟踪信息, e.printStackTrace();
方案③:获取异常的原因信息, println(e.getMessage());

注意1:多重catch时,父类异常需要写在最后。
注意2:finally无论是否有异常或return,都会被执行。

1
2
3
4
5
6
7
8
9
10
11
try {
//可能出现异常的代码
} catch (Exception e) {
//异常处理的相关代码(三种方案)
//方案1:自定义处理, 如println();
//方案2:打印堆栈跟踪信息, e.printStackTrace();
//方案3:获取异常的原因信息, println(e.getMessage());
[... 多重 catch () ...] // 遵循从子到父的顺序,父类异常在最后。
} finally {
//无论是否出现异常都需要执行的代码结构(不受return影响),常用于释放资源
}

实例代码测试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class TestTryCatch {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int result = 0;

try {
System.out.println("请输入一个数:");
int num1 = input.nextInt();
System.out.println("请输入一个数:");
int num2 = input.nextInt();
result = num1 / num2;

} catch (ArithmeticException e) { // num2==0
System.out.println("除数不能为0"); // 处理方案1. 自定义处理
// e.printStackTrace(); // 处理方案2. 打印堆栈跟踪信息
System.out.println(e.getMessage()); // 处理方案3. 获取异常的原因信息message
result = 0;
return;
} catch (InputMismatchException e) {
System.out.println("请输入正确的整数");
} catch (Exception e) { // Exception 为异常类最顶端父类,写最后去捕获
System.out.println("未知错误:" + e.toString());
} finally {
System.out.println("无论是否有异常或return,都会被执行到...");
}

System.out.println("结果:" + result);

input.close();
}
}

image-20230316135810912


01-异常体系
https://janycode.github.io/2016/04/28/02_编程语言/01_Java/01_JavaSE/04_异常处理/01-异常体系/
作者
Jerry(姜源)
发布于
2016年4月28日
许可协议