Java 编程语言使用异常来处理错误和其他异常事件。
异常是程序执行期间发生的、会打断指令正常流程的事件。 在 Java 中,异常是显式抛出的,抛出异常的动作称为_抛出异常_。 处理异常的动作称为_捕获异常_。
在 Java 中,所有异常都是 Exception 类的子类,而 Exception 类本身又是 Throwable 的子类。
Java 将异常分为两类:
_受检异常_是应用程序应当预见、并能从中恢复的异常情况。
受检异常的一个例子是 FileNotFoundException,当方法试图读取一个不存在的文件时就会发生。
这类异常在编译期检查:抛出受检异常的方法应当在其方法签名中说明这一点;调用可能抛出受检异常的方法的代码,必须处理该异常,否则代码无法通过编译。
所有受检异常都是 Exception 的子类,且不继承 RuntimeException。
_非受检异常_是应用程序通常无法预见、也无法从中恢复的异常情况。
非受检异常的一个例子是 NullPointerException,当方法期望一个非 null 值、却收到 null 时就会发生。
这类异常不在编译期检查:抛出非受检异常的方法不要求在其方法签名中说明这一点;调用可能抛出非受检异常的方法的代码,也不必处理它。
所有非受检异常都继承自 RuntimeException,而 RuntimeException 本身又继承自 Exception。
Java 中的方法可以使用 throw 语句抛出一个异常。
从方法中抛出受检异常时,必须使用 throws 关键字在方法签名中说明这一点,如下例所示。
这会迫使调用方的代码预见到可能抛出异常,并相应地处理它。
public class InsufficientBalanceException extends Exception {
}
public class BankAccount {
public void withdraw(double amount) throws InsufficientBalanceException {
if (balance < amount) {
throw new InsufficientBalanceException();
}
// rest of the method implementation
}
}
从方法中抛出非受检异常时,不要求在方法签名中说明这一点,尽管也支持这样做。
public class BankAccount {
public void withdraw(double amount) {
if (amount < 0) {
throw new IllegalArgumentException("Cannot withdraw a negative amount");
}
// rest of the method implementation
}
}
在 Java 中,处理异常要使用 try、catch 和 finally 关键字。
try 块中。try 块后面跟着一个或多个 catch 块,用来捕获 try 块中抛出的异常。catch 块后面可选地跟一个 finally 块,它总是在 try 块之后执行,无论是否抛出了异常。下面的例子展示了这些关键字如何工作:
public class ATM {
public void withdraw(BankAccount bankAccount, double amount) {
try {
System.out.println("Withdrawing " + amount);
bankAccount.withdraw(amount);
System.out.println("Withdrawal succeeded");
} catch (InsufficientBalanceException) {
System.out.println("Withdrawal failed: insufficient balance");
} catch (RuntimeException e) {
System.out.println("Withdrawal failed: " + e.getMessage());
} finally {
System.out.println("Current balance: " + bankAccount.getBalance());
}
}
}
在这个例子中,没有抛出异常时,会打印以下内容:
Withdrawing 10.0
Withdrawal succeeded
Current balance: 5.0
不过,如果 bankAccount.withdraw(amount) 语句抛出了 InsufficientBalanceException,则会打印以下内容:
Withdrawing 10.0
Withdrawal failed: insufficient balance
Current balance: 5.0
或者,如果 bankAccount.withdraw(amount) 抛出了非受检异常,则会打印以下内容:
Withdrawing -10.0
Withdrawal failed: Cannot withdraw a negative amount
Current balance: 5.0
Java 还有一个单独的类别,称为_错误_,指的是应用程序外部的严重问题。
错误的一个例子是 OutOfMemoryError,当应用程序试图使用超过系统可用内存的内存时就会发生。
和非受检异常一样,错误也不在编译期检查。 区别在于,它们代表系统层面的问题,通常由 Java 虚拟机或环境抛出,而不是由应用程序抛出。 应用程序通常不应尝试捕获或处理它们。
Java 中的所有错误都继承自 Error 类。
如前所述,异常是会打断指令正常流程的事件,用于处理_异常事件_。 因此,不建议在应用程序中使用异常来控制流程。