异常类层次结构
本课属于 Coddy Java 学习旅程的“面向对象编程”单元。第 59 课,共 87 课。
Java 的异常处理系统建立在以 Throwable 类为根的组织良好的类层次结构之上。了解这一层次结构有助于你更有效地捕获和处理异常。
最顶层是 Throwable,它是所有异常和错误的父类。它有两个直接子类:
Throwable
├── Error // 严重问题(不要捕获这类错误)
└── Exception // 可恢复的问题
└── RuntimeException // 非受检异常错误表示应用程序不应尝试处理的严重问题,例如 OutOfMemoryError 或 StackOverflowError。这些错误表明 JVM 本身存在根本性问题。
Exception 是你最常使用的分支。它分为两类:已检查异常(Exception 的直接子类)和未检查异常(RuntimeException 的子类)。
// 常见的异常类
Exception
├── IOException // 文件或网络问题
├── SQLException // 数据库问题
└── RuntimeException
├── NullPointerException
├── ArrayIndexOutOfBoundsException
└── IllegalArgumentException由于异常是类,因此它们遵循继承规则。捕获父异常类型时,也会捕获它的所有子类:
try {
// 一些代码
} catch (Exception e) {
// 捕获所有异常(通常范围太广)
}try {
// 一些代码
} catch (RuntimeException e) {
// 只捕获运行时异常及其子类的异常
}这个层级结构让你在处理错误时,可以根据需要选择具体或通用的程度,也是创建自定义异常的基础。
挑战
简单让我们构建一个异常分析器,演示 Java 的异常层次结构在实际中的工作方式!你将创建一个系统,在不同的具体层级捕获异常,并报告捕获到的类型。
你将把代码分成三个文件:
ExceptionThrower.java:创建一个类,根据输入触发不同类型的异常。这个类应包含三个静态方法:triggerRuntime(String type)- 根据类型字符串抛出不同的运行时异常:- 如果 type 是
"null",则抛出带有消息"Null value encountered"的NullPointerException - 如果 type 是
"index",则抛出带有消息"Invalid index"的ArrayIndexOutOfBoundsException - 如果 type 是
"argument",则抛出带有消息"Bad argument"的IllegalArgumentException
triggerArithmetic()- 抛出带有消息"Division error"的ArithmeticExceptiontriggerGeneric()- 抛出带有消息"Generic runtime error"的IllegalStateException(其层次结构为 Exception > RuntimeException > IllegalStateException)- 如果 type 是
ExceptionAnalyzer.java:创建一个类,在不同的异常层次捕获异常,并识别捕获到的异常。包含以下静态方法:analyzeSpecific(String type)- 在 try 块中调用ExceptionThrower.triggerRuntime(type)。分别为NullPointerException、ArrayIndexOutOfBoundsException和IllegalArgumentException编写 catch 块。对于每种异常,打印:Caught specific: [exception class simple name],然后打印Message: [exception message]analyzeWithParent()- 在 try 块中调用ExceptionThrower.triggerArithmetic()。使用RuntimeException(父类型)捕获异常。打印:Caught via parent: RuntimeException,然后打印Actual type: [exception class simple name]analyzeWithGrandparent()- 在 try 块中调用ExceptionThrower.triggerGeneric()。使用Exception(层次结构中更高的类型)捕获异常。打印:Caught via grandparent: Exception,然后打印Actual type: [exception class simple name]Main.java:整合你的异常分析器!你将接收一个输入:异常类型字符串(可以是"null"、"index"或"argument")。首先,打印
=== Specific Catch ===,并使用输入调用analyzeSpecific。然后打印一个空行、
=== Parent Catch ===,并调用analyzeWithParent。最后,打印一个空行、
=== Grandparent Catch ===,并调用analyzeWithGrandparent。
你将接收一个输入:要触发的异常类型("null"、"index" 或 "argument")。
使用 e.getClass().getSimpleName() 获取异常的类名,并使用 e.getMessage() 获取异常消息。这个挑战展示了捕获父异常类型时也会捕获它的所有子类型,这是决定异常处理应当具体到什么程度时的一个关键概念!
亲手试试
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String type = scanner.nextLine();
// TODO: 输出 "=== Specific Catch ===",并调用 ExceptionAnalyzer.analyzeSpecific(type)
// TODO: 先输出一个空行,再输出 "=== Parent Catch ===",然后调用 ExceptionAnalyzer.analyzeWithParent()
// TODO: 先输出一个空行,再输出 "=== Grandparent Catch ===",然后调用 ExceptionAnalyzer.analyzeWithGrandparent()
}
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: Java 在线编译器