Java try catch详解(附带实例)
在 Java 程序中,捕获异常是通过 try-catch 语句实现的,最基本的 try-catch 语句语法如下:
例如,日期格式化类 DateFormat 的日期解析方法 parse(),其完整定义如下:
下面看一个 try-catch 示例:
在 try 代码块中,尝试将字符串转换为整数,并打印输入的整数。如果用户输入的字符串无法转换为整数,则会跳转到 catch 代码块,捕获并处理 NumberFormatException 异常,并提示用户输入的不是有效的整数。
在 catch 代码块中处理了异常,并打印相应的错误信息。
无论是否发生异常,最后都会关闭 Scanner 资源,以确保程序在结束时正确释放资源。
如果在程序运行过程中输入的是非整数,则引发异常并打印“输入的不是有效的整数。”,如下图所示:

图 1 引发异常
如果输入的是有效的整数,则正常执行并打印“输入的整数是:×××”,如下图所示:

图 2 正常执行
代码解释如下:
代码第 ① 处创建了一个名为 scanner 的 Scanner 对象,用于从标准输入流(键盘)读取用户输入。将这个对象与 System.in 关联,以便从控制台接收输入。
代码第 ② 处的 String input = scanner.nextLine() 方法从用户输入中读取一行文本,并将其存储在名为 input 的字符串变量中。用户在控制台输入的内容会被保存在 input 变量中。
代码第 ③ 处开始一个 try 代码块,用于包含可能会引发异常的代码。在这个例子中,尝试将用户输入的字符串转换为整数。
代码第 ④ 处用 Integer.parseInt() 方法将 input 字符串转换为整数。如果 input 字符串无法转换为整数,就会抛出 NumberFormatException 异常。
代码第 ⑤ 处使用 catch 块捕获 NumberFormatException 异常,这是在 try 代码块中发生转换错误时会抛出的异常。
代码第 ⑥ 处的 scanner.close() 方法关闭 Scanner 对象。通过关闭 Scanner 对象,释放底层资源,即标准输入流(键盘),以确保在程序结束时正确释放资源。
示例代码如下:
如果解析成功,程序将继续执行算术运算,即将 100 除以输入的数。如果输入的数是零(尝试除以零),这一行可能会抛出 ArithmeticException 异常。
程序使用多个 catch 代码块来处理不同类型的异常:
如果程序运行过程中输入的是 0,则引发除 0 异常,如下图所示,其他的异常情况不再测试。

图 3 finally代码块
使用 finally 代码块的示例代码如下:

图 4 执行finally代码块
自动资源管理是在 try 语句上的扩展,语法如下:
示例代码如下:
try { // 可能会发生异常的语句 } catch (Throwable e) { // 处理异常 e }
Java try代码块
try 代码块中应该包含执行过程中可能会发生异常的语句。一条语句是否有可能发生异常,要看语句中调用的方法。例如,日期格式化类 DateFormat 的日期解析方法 parse(),其完整定义如下:
try { // 可能会发生异常的语句 } catch (Throwable e) { // 处理异常 e }方法后面的 throws ParseException 说明:当调用 parse() 方法时有可能产生 ParseException 异常。
public Date parse(String source) throws ParseException类方法、实例方法和构造方法都可以声明抛出异常,凡是抛出异常的方法都可以通过 try-catch 进行捕获,当然,运行时异常可以不捕获。一个方法声明抛出什么样的异常需要查询 API 文档。
Java catch代码块
每个 try 代码块可以伴随一个或多个 catch 代码块,用于处理 try 代码块中可能发生的多种异常。catch(Throwable e)
语句中的 e 是异常对象,e 必须是 Throwable 的子类,异常对象 e 的作用域在该 catch 代码块中。下面看一个 try-catch 示例:
import java.util.Scanner; public class ExceptionExample { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("请输入一个整数:"); String input = scanner.nextLine(); try { int number = Integer.parseInt(input); System.out.println("输入的整数是:" + number); } catch (NumberFormatException e) { System.out.println("输入的不是有效的整数。"); } // 关闭 scanner scanner.close(); } }在上面的示例中,使用 Scanner 获取用户输入的字符串,并尝试将其转换为整数。如果用户输入的字符串无法转换为整数,就会抛出 NumberFormatException 异常。
在 try 代码块中,尝试将字符串转换为整数,并打印输入的整数。如果用户输入的字符串无法转换为整数,则会跳转到 catch 代码块,捕获并处理 NumberFormatException 异常,并提示用户输入的不是有效的整数。
在 catch 代码块中处理了异常,并打印相应的错误信息。
无论是否发生异常,最后都会关闭 Scanner 资源,以确保程序在结束时正确释放资源。
如果在程序运行过程中输入的是非整数,则引发异常并打印“输入的不是有效的整数。”,如下图所示:

图 1 引发异常
如果输入的是有效的整数,则正常执行并打印“输入的整数是:×××”,如下图所示:

图 2 正常执行
代码解释如下:
代码第 ① 处创建了一个名为 scanner 的 Scanner 对象,用于从标准输入流(键盘)读取用户输入。将这个对象与 System.in 关联,以便从控制台接收输入。
代码第 ② 处的 String input = scanner.nextLine() 方法从用户输入中读取一行文本,并将其存储在名为 input 的字符串变量中。用户在控制台输入的内容会被保存在 input 变量中。
代码第 ③ 处开始一个 try 代码块,用于包含可能会引发异常的代码。在这个例子中,尝试将用户输入的字符串转换为整数。
代码第 ④ 处用 Integer.parseInt() 方法将 input 字符串转换为整数。如果 input 字符串无法转换为整数,就会抛出 NumberFormatException 异常。
代码第 ⑤ 处使用 catch 块捕获 NumberFormatException 异常,这是在 try 代码块中发生转换错误时会抛出的异常。
代码第 ⑥ 处的 scanner.close() 方法关闭 Scanner 对象。通过关闭 Scanner 对象,释放底层资源,即标准输入流(键盘),以确保在程序结束时正确释放资源。
使用多catch代码块
如果 try 代码块中有很多语句会发生异常,而且发生的异常种类又很多,那么可以在 try 后面跟多个 catch 代码块。多 catch 代码块的语法如下:try { // 可能会发生异常的语句 } catch (Throwable e1) { // 处理异常 e1 } catch (Throwable e2) { // 处理异常 e2 } catch (Throwable e3) { // 处理异常 e3 ... }在有多个 catch 代码块的情况下,当一个 catch 代码块捕获到一个异常时,其他的 catch 代码块就不再进行匹配。当捕获的多个异常类之间存在父子关系时,捕获异常顺序与 catch 代码块的顺序有关。一般先捕获子类,后捕获父类,否则捕获不到子类。
示例代码如下:
import java.util.Scanner; class ExceptionExample { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); try { System.out.print("请输入一个整数:"); String input = scanner.nextLine(); int number = Integer.parseInt(input); System.out.println("输入的整数是:" + number); int dividend = 100; int result = dividend / number; // 尝试除以零的算术运算,引发 ArithmeticException 异常 System.out.println("结果:" + result); } catch (NumberFormatException e) { System.out.println("输入的不是有效的整数。"); } catch (ArithmeticException e) { System.out.println("发生了算术异常:" + e.getMessage()); } catch (Exception e) { System.out.println("发生了其他异常。"); } scanner.close(); } }上述程序代码使用 Scanner 对象获取用户输入的整数,它尝试将输入解析为整数,使用 Integer.parseInt(input)。如果输入不是有效的整数,这一行可能会抛出 NumberFormatException 异常。
如果解析成功,程序将继续执行算术运算,即将 100 除以输入的数。如果输入的数是零(尝试除以零),这一行可能会抛出 ArithmeticException 异常。
程序使用多个 catch 代码块来处理不同类型的异常:
- 如果在解析过程中发生 NumberFormatException 异常,程序会捕获它并打印“输入的不是有效的整数。”;
- 如果在算术运算中发生 ArithmeticException 异常(如除 0 异常),程序会捕获它并打印“发生了算术异常:”,后面跟着异常的信息;
- 如果发生其他任何异常,而这些异常没有被上面的特定 catch 代码块捕获,它们会被通用的 Exception 块所捕获,程序会打印“发生了其他异常。”。
如果程序运行过程中输入的是 0,则引发除 0 异常,如下图所示,其他的异常情况不再测试。
Java finally语句
try-catch 语句后面还可以跟有一个 finally 代码块,无论 try 代码块正常结束还是 catch 代码块异常结束都会执行 finally 代码块,如下图所示。
图 3 finally代码块
使用 finally 代码块的示例代码如下:
import java.util.Scanner; public class ExceptionExample { public static void main(String[] args) { Scanner scanner = null; try { scanner = new Scanner(System.in); System.out.print("请输入一个整数:"); String input = scanner.nextLine(); int number = Integer.parseInt(input); System.out.println("输入的整数是:" + number); int dividend = 100; int result = dividend / number; // 尝试除以零的算术运算,引发 ArithmeticException 异常 System.out.println("结果:" + result); } catch (NumberFormatException e) { System.out.println("输入的不是有效的整数。"); } catch (ArithmeticException e) { System.out.println("发生了算术异常:" + e.getMessage()); } catch (Exception e) { System.out.println("发生了其他异常。"); } finally { if (scanner != null) { // 确保无论发生什么情况,都关闭 Scanner 资源 scanner.close(); System.out.printf("资源已释放。"); } } } }程序运行过程如下图所示,无论是否发生了异常,都保证执行了 finally 代码块:

图 4 执行finally代码块
Java自动资源管理
使用 finally 代码块释放资源会导致程序代码大量增加,一个 finally 代码块往往比正常执行的程序还要多。在 Java 7 之后提供的自动资源管理技术可以替代 finally 代码块,优化代码结构,提高程序可读性。自动资源管理是在 try 语句上的扩展,语法如下:
try { // 声明或初始化资源语句 // 可能会生成异常语句 } catch (Throwable e1) { // 处理异常 e1 } catch (Throwable e2) { // 处理异常 e2 ... } catch (Throwable eN) { // 处理异常 eN }在 try 语句后面添加一对小括号“()”,其中是声明或初始化资源语句,可以有多条语句,语句之间用分号“;”分隔。
示例代码如下:
import java.util.Scanner; public class ExceptionExample { public static void main(String[] args) { try (Scanner scanner = new Scanner(System.in)) { System.out.print("请输入一个整数:"); String input = scanner.nextLine(); int number = Integer.parseInt(input); System.out.println("输入的整数是:" + number); int dividend = 100; int result = dividend / number; // 尝试除以零的算术运算,引发 ArithmeticException 异常 System.out.println("结果:" + result); } catch (NumberFormatException e) { System.out.println("输入的不是有效的整数。"); } catch (ArithmeticException e) { System.out.println("发生了算术异常:" + e.getMessage()); } catch (Exception e) { System.out.println("发生了其他异常。"); } } }在这个改进后的代码中,我们使用了自动资源管理 Scanner 对象。Scanner 类实现了 AutoCloseable 接口,因此在 try 代码块运行结束时会自动调用 scanner.close() 方法来关闭资源。无论代码是否发生异常,Scanner 对象都会被正确释放。这样的写法使代码更简洁,同时确保了资源的可靠释放。