201. Java 异常 - 如何抛出异常
在 Java
中,抛出异常是一个核心概念。无论是你的代码、第三方包的代码,还是 Java 平台本身,任何地方都可以抛出异常。了解如何使用 throw
语句抛出异常,并理解异常类的继承体系,是编写健壮程序的关键。
🧐 何时抛出异常?
抛出异常是指在程序执行过程中遇到错误时,通过 throw
语句主动抛出一个异常,告知程序出现了无法继续正常执行的问题。
Java 中的异常体系非常丰富,所有异常类都继承自 Throwable
类,Java 为不同类型的异常提供了不同的类,以便程序可以根据异常类型采取适当的处理措施。
🧩 Java 异常体系
Java 平台提供了许多预定义的异常类。所有这些异常类都继承自 Throwable
类。Throwable
有两个主要的子类:
Error
类 :表示严重的错误,通常是系统层面的问题,例如OutOfMemoryError
。这些错误一般不应该被程序捕获和处理。Exception
类 :表示程序中的各种异常情况。Exception
又分为两类:- 检查异常(Checked Exceptions) :这些异常在编译时必须被处理,程序员必须捕获或声明抛出。例如,
IOException
、SQLException
。 - 非检查异常(Unchecked Exceptions) :也叫运行时异常,这些异常通常是由于程序中的逻辑错误引起的。程序员可以选择捕获或忽略它们。例如,
NullPointerException
、ArrayIndexOutOfBoundsException
。
- 检查异常(Checked Exceptions) :这些异常在编译时必须被处理,程序员必须捕获或声明抛出。例如,
🔨 使用 throw
抛出异常
当你的代码检测到错误或不正常的情况时,你可以使用 throw
语句抛出一个异常。
示例:抛出 IllegalArgumentException
java
public class Calculator {
public int divide(int a, int b) {
if (b == 0) {
throw new IllegalArgumentException("Division by zero is not allowed!");
}
return a / b;
}
}
在上面的例子中,我们使用 throw
语句抛出了一个 IllegalArgumentException
,当除数 b
为零时,我们明确地提示这个错误信息。调用 divide
方法时,如果传入 0
作为除数,就会抛出异常。
如何捕获这个异常:
java
public class TestCalculator {
public static void main(String[] args) {
Calculator calculator = new Calculator();
try {
System.out.println(calculator.divide(10, 0));
} catch (IllegalArgumentException e) {
System.err.println("Error: " + e.getMessage());
}
}
}
在这个例子中,我们捕获了 IllegalArgumentException
,并打印出了异常信息。
🛠️ 创建自定义异常类
有时候,Java 自带的异常类不足以表达你的业务逻辑问题。在这种情况下,你可以创建自己的异常类。这对于开发自己的类库或 API
非常重要,用户通过这些自定义异常可以明确地区分不同类型的错误。
示例:自定义 InsufficientFundsException
java
public class InsufficientFundsException extends Exception {
public InsufficientFundsException(String message) {
super(message);
}
}
在上面的例子中,我们创建了一个名为 InsufficientFundsException
的自定义异常类,继承自 Exception
。这个异常可以用来表示余额不足的情况。
使用自定义异常:
java
public class BankAccount {
private double balance;
public BankAccount(double balance) {
this.balance = balance;
}
public void withdraw(double amount) throws InsufficientFundsException {
if (amount > balance) {
throw new InsufficientFundsException("Insufficient funds for this withdrawal.");
}
balance -= amount;
}
}
在上面的代码中,withdraw
方法如果遇到余额不足的情况,将抛出我们自定义的 InsufficientFundsException
。
🔗 链式异常(Chained Exceptions)
有时在处理异常时,可能会发生一种情况:一个异常被捕获后,你需要抛出另一个异常。为此,Java 提供了链式异常机制,使你能够将一个异常"包装"成另一个异常,以便将原始的异常信息传递给上层调用者。
示例:链式异常
java
public class Example {
public void methodA() {
try {
methodB();
} catch (IOException e) {
throw new RuntimeException("Runtime exception occurred while handling I/O", e);
}
}
public void methodB() throws IOException {
throw new IOException("File not found");
}
}
在上面的例子中,methodA
捕获了 IOException
并将其包装为 RuntimeException
,抛给调用者。这里,原始的 IOException
被作为参数传递给新的异常构造函数,形成了一个"链式异常"。
📝 总结
- 抛出异常 :使用
throw
语句抛出异常,通常用于捕获无法继续执行的错误情况。 - 异常类的继承体系 :Java 提供了丰富的异常类供我们使用,所有异常类都继承自
Throwable
。 - 自定义异常:你可以创建自己的异常类,帮助你在应用程序中传递特定的错误信息。
- 链式异常:链式异常允许你将一个异常"包装"成另一个异常,并保留原始异常的信息。
通过掌握如何抛出异常,学员能够更好地控制错误处理流程,确保程序在遇到问题时能够以合适的方式进行反馈和处理。