Java 内置异常可以处理很多通用错误,但真实项目经常会遇到业务规则错误。例如“库存不足”不是语法错误,也不是类型错误,而是一条业务规则被违反。
定义异常类
自定义受检异常(custom checked exception)通常继承 Exception。简单异常类可以先只定义一个构造方法,将 throw 时传入的具体信息转交给 super()。名称应清楚表达错误含义,让调用者无需解析文字就能识别错误类别。
本节按“一类一个文件”组织代码,接口也单独保存。文件名与类型名一致;同一组示例的文件放在同一目录,不同组示例请使用独立目录,避免同名类互相冲突。
OutOfStockException.java
public class OutOfStockException extends Exception {
OutOfStockException(String message) {
super(message);
}
}Main.java
public class Main {
public static void main(String[] args) throws OutOfStockException {
throw new OutOfStockException("Notebook is out of stock.");
}
}这里的 Main.java 只演示抛出异常:throws 声明它可能向外抛出该异常,运行时会报告未捕获的异常。下面的库存案例会展示如何用 catch 处理它。
知识测验
题目
自定义异常通常继承哪个类?
库存案例
IllegalArgumentException 表示购买数量本身不合理;OutOfStockException 表示数量虽然合理,但当前库存无法满足。不同异常表达不同层次的问题。
OutOfStockException.java
public class OutOfStockException extends Exception {
OutOfStockException(String message) {
super(message);
}
}Product.java
public class Product {
private final String name;
private int stock;
Product(String name, int stock) {
this.name = name;
this.stock = stock;
}
void purchase(int quantity) throws OutOfStockException {
if (quantity <= 0) {
throw new IllegalArgumentException("Quantity must be greater than 0.");
}
if (quantity > stock) {
throw new OutOfStockException(name + " is out of stock.");
}
stock -= quantity;
}
int getStock() {
return stock;
}
}Main.java
public class Main {
public static void main(String[] args) {
Product product = new Product("Notebook", 5);
try {
product.purchase(3);
System.out.println("Remaining stock: " + product.getStock());
product.purchase(4);
} catch (OutOfStockException exception) {
System.out.println("Purchase failed: " + exception.getMessage());
}
}
}Remaining stock: 2
Purchase failed: Notebook is out of stock.知识测验
题目
OutOfStockException 比普通 Exception 更有价值的原因是什么?
为什么要自定义异常
自定义异常的价值是语义。捕获 OutOfStockException 后,界面可以提供“补货”或“更换商品”;捕获 IllegalArgumentException 时,则应要求用户修改数量。调用方也可以分别记录、重试或向上继续抛出这些错误。
| 错误 | 含义 | 可能处理 |
|---|---|---|
IllegalArgumentException | 参数无效 | 要求重新输入 |
OutOfStockException | 库存不足 | 补货或换商品 |
知识测验
题目
库存案例中,哪项分类最合理?
动手练习
定义 IllegalTriangleException
- 定义继承 Exception 的 IllegalTriangleException。
- Triangle 构造方法对非正数边抛出 IllegalArgumentException。
- 三边不满足任意两边之和大于第三边时,抛出 IllegalTriangleException。
- 主程序分别捕获两个异常,并输出不同提示。