异常的抛出与捕捉

为了保证程序有效地执行,需要对抛出的异常进行相应的处理。在 Java 中,如果某个方法抛出异常,既可以在当前方法中进行捕捉,而后处理该异常,也可以将异常向上抛出,交由方法调用者来处理。本节将讲解 Java 中捕获异常的方法。

抛出异常

异常抛出后,如果不做任何处理,程序就会被终止。例如,将一个字符串转换为整型,可以通过 Integer 类的 parseInt() 方法来实现。但如果该字符串不是数字形式的,那么 parseInt() 方法就会抛出异常,程序将在出现异常的位置处被终止,不再执行下面的语句。

【例9.2】控制台输出“lili年龄是:20L”(实例位置:资源包\TM\sl\9\2)

在项目中创建 Thundering 类,在主方法中实现将不是数字形式的字符串转换为 int 型。运行程序,系统会报出异常提示。实例代码如下:

public class Thundering { // 创建类
	public static void main(String[] args) { // 主方法
		String str = "lili"; // 定义字符串
		System.out.println(str + "年龄是:"); // 输出的提示信息
		int age = Integer.parseInt("20L"); // 数据类型的转换
		System.out.println(age); // 输出信息
	}
}

运行结果如图9.2所示。

image 2024 03 01 12 20 32 273
Figure 1. 图9.2 例9.2的运行结果

从图9.2中可以看出,本实例报出的是 NumberFormatException(字符串转换为数字)异常。提示信息 “lili年龄是:” 已经输出,可知该句代码之前并没有异常,而变量 age 没有输出,可知程序在执行类型转换代码时已经被终止。

使用 try…​catch…​finally 语句捕捉异常

Java 语言的异常捕获结构由 try、catch 和 finally 3 部分组成。其中:try 语句块存放的是可能发生异常的 Java 语句;catch 语句块在 try 语句块之后,用来激发被捕获的异常;finally 语句块是异常处理结构的最后执行部分,无论 try 语句块中的代码如何退出,都将执行 finally 语句块。语法如下:

try {
    // 程序代码块
} catch(Exceptiontype1 e) {
    // 对 Exceptiontype1 的处理
} catch(Exceptiontype2 e) {
    // 对 Exceptiontype2 的处理
} finally {
    // 程序代码块
}

通过异常处理器的语法可知,异常处理器大致分为 try…catch 语句块和 finally 语句块。

try…catch语句块

下面对例9.2中的代码进行修改。

【例9.3】捕获例9.2中主方法抛出的异常(实例位置:资源包\TM\sl\9\3)

在项目中创建 Take 类,在主方法中使用 try…catch 语句块将可能出现的异常语句进行异常处理。实例代码如下:

public class Take { // 创建类
	public static void main(String[] args) {
		try { // try语句中包含可能出现异常的程序代码
			String str = "lili"; // 定义字符串变量
			System.out.println(str + "年龄是:"); // 输出的信息
			int age = Integer.parseInt("20L"); // 数据类型转换
			System.out.println(age);
		} catch (Exception e) { // catch语句块用来获取异常信息
			e.printStackTrace(); // 输出异常性质
		}
		System.out.println("program over"); // 输出信息
	}
}

运行结果如图9.3所示。

image 2024 03 01 12 25 16 553
Figure 2. 图9.3 例9.3的运行结果

从图9.3中可以看出,程序仍然输出最后的提示信息,没有因为异常而终止。在例9.3中,将可能出现异常的代码用 try…catch 语句块进行处理,当 try 语句块中的语句发生异常时,程序就会跳转到 catch 语句块中执行,执行完 catch 语句块中的程序代码后,将继续执行 catch 语句块后的其他代码,而不会执行 try 语句块中发生异常语句后面的代码。由此可知,Java 的异常处理是结构化的,不会因为一个异常影响整个程序的执行。

有时为了编程简单会忽略 catch 语句后的代码,这样 try…catch 语句就成了一种摆设,一旦程序在运行过程中出现了异常,就会导致最终运行结果与期望的不一致,而错误发生的原因很难查找。因此要养成良好的编程习惯,最好在 catch 语句块中写入处理异常的代码。

finally语句块

完整的异常处理语句一定要包含 finally 语句,无论程序中有无异常发生,并且无论之前的 try…catch 语句块是否被顺利执行完毕,都会执行 finally 语句。但是,在以下 4 种特殊情况下,finally 块不会被执行:

  • 在 finally 语句块中发生了异常。

  • 在前面的代码中使用了 System.exit() 退出程序。

  • 程序所在的线程死亡。

  • 关闭 CPU。

编程训练(答案位置:资源包\TM\sl\9\编程训练)

【训练1】简易计算器 模拟一个简单的整数计算器(只能计算两个整数之间的加、减、乘、除运算),使用 try…catch 语句块捕捉 InputMismatchException(控制台输入的不是整数)异常。

【训练2】校验银行取款金额 使用 try…catch 语句块和 finally 语句块模拟一个取款过程。某个银行账号现有余额 1023.79 元,且银行规定每次取款金额必须是整数,当在控制台上输入的取款金额不是整数时,会捕捉到数字格式转换异常。