使用 try...catch 处理异常
Java 中 try...catch
语句用于处理异常,防止程序异常终止。在本教程中,我们将通过示例学习 Java 中的 try catch 语句用法。
在本教程中,我们将通过示例学习 Java 中的 try catch 语句用法。
在 Java 中,异常可以分为两种类型:
- 不受检查的异常: 它们不是在编译时检查,而是在运行时检查。例如:
RuntimeException
,ArithmeticException
,NullPointerException
,ArrayIndexOutOfBoundsException
,Error
类下的异常等。 - 受检查的异常: 它们在编译时被检查。例如
IOException
,InterruptedException
等。
请参阅 Java 异常以了解有关受检查的异常和不受检查的异常的详细信息。
对于受检查的异常,编译期间必须要求使用 try...catch
语句处理异常或者在方法上使用 throws
关键字声明。
try…catch
Java 中 try...catch
语句用于处理异常,防止程序异常终止。
try...catch
语句的语法:
try {
// code
}
catch(Exception e) {
// code
}
try
块包含可能产生异常的代码。 catch
块包括 try
块当发生异常时需要执行的代码。
示例:Java try…catch 块
public class Main {
public static void main(String[] args) {
try {
int divideByZero = 5 / 0;
System.out.println("Rest of code in try block");
}
catch (ArithmeticException e) {
System.out.println("ArithmeticException => " + e.getMessage());
}
}
}
输出
ArithmeticException => / by zero
在上面的例子中,注意这一行,
int divideByZero = 5 / 0;
在这里,我们试图将一个数除以 0
。在这种情况下,会发生异常。因此,我们将此代码包含在 try
块中。
当程序执行到这行代码时,就会发生 ArithmeticException
异常。异常被 catch
块捕获并执行 catch
块内的代码。
try…finally
我们还可以将 try
块与 finally
块一起使用。
在这种情况下,无论 try
块中是否存在异常, finally
块都会被执行。
示例:Java try…finally 块
public class Main {
public static void main(String[] args) {
try {
int divideByZero = 5 / 0;
}
finally {
System.out.println("Finally block is always executed");
}
}
}
输出
Finally block is always executed
Exception in thread "main" java.lang.ArithmeticException: / by zero
at Main.main(Main.java:6)
在上面的示例中,我们将 try
块与 finally
块一起使用。我们可以看到 try
块内的代码导致了异常。
但是,无论异常如何, finally
块内的代码都会执行。
try…catch…finally
在 Java 中,我们也可以在 try...catch
块之后使用 finally
块。例如,
import java.io.*;
class ListOfNumbers {
// 整数数组
private int[] list = {5, 6, 8, 9, 2};
// 将数组中的元素写入文件
public void writeList() {
PrintWriter out = null;
try {
System.out.println("Entering try statement");
// 打开文件: OutputFile.txt
out = new PrintWriter(new FileWriter("OutputFile.txt"));
// 向文件 OutputFile.txt 中写入值
for (int i = 0; i < 7; i++) {
out.println("Value at: " + i + " = " + list[i]);
}
} catch (Exception e) {
System.out.println("Exception => " + e.getMessage());
} finally {
// 检查 PrintWriter 对象是否已经开启
if (out != null) {
System.out.println("Closing PrintWriter");
// 关闭 PrintWriter 对象
out.close();
} else {
System.out.println("PrintWriter not open");
}
}
}
}
public class Main {
public static void main(String[] args) {
ListOfNumbers list = new ListOfNumbers();
list.writeList();
}
}
输出
Entering try statement
Exception => Index 5 out of bounds for length 5
Closing PrintWriter
在上面的例子中,我们创建了一个名为 list
的数组和一个名为 OutputFile.txt
的文件。在这里,我们试图从数组中读取数据并存储到文件中。
注意下面的代码:
for (int i = 0; i < 7; i++) {
out.println("Value at: " + i + " = " + list[i]);
}
这里,数组的大小为 5
,数组的最后一个元素为 list[4]
。但是,我们试图尝试访问 list[5]
和 list[6]
处的元素 。因此,程序会生成数组越界异常。
由于 finally
块总是被执行,我们在 finally 块中包含了关闭 PrintWriter
代码。
使用 finally
块来包含重要的清理代码(例如关闭文件或连接)是一种很好的做法。
注意:有一些情况下不会执行 finally
块:
- 使用
System.exit()
方法退出程序 - 在
finally
块中发生异常 - 执行线程死掉了
多个 Catch 块
对于每个 try
块,可以有零个或多个 catch
块。多个 catch
块允许我们以不同的方式处理每个异常。
每个 catch
块的参数类型表示它可以处理的异常类型。例如,
class ListOfNumbers {
public int[] arr = new int[10];
public void writeList() {
try {
arr[10] = 11;
} catch (NumberFormatException e1) {
System.out.println("NumberFormatException => " + e1.getMessage());
} catch (IndexOutOfBoundsException e2) {
System.out.println("IndexOutOfBoundsException => " + e2.getMessage());
} catch (Exception e3) {
System.out.println("Exception => " + e3.getMessage());
}
}
}
public class Main {
public static void main(String[] args) {
ListOfNumbers list = new ListOfNumbers();
list.writeList();
}
}
输出
IndexOutOfBoundsException => Index 10 out of bounds for length 10
在这个例子中,我们已经创建了一个名为 arr
整数数组,数组的大小是 10。由于数组索引从0开始,因此数组的最后一个元素位于 arr[9]
。注意声明,
arr[10] = 11;
在这里,我们试图为索引 10 赋值。因此,发生了 IndexOutOfBoundException
异常。
当 try
块中发生异常时:
- 异常被抛出到第一个
catch
块。第一个catch
块不处理IndexOutOfBoundsException
,异常被传递到下一个catch
块。 - 第二个
catch
块是适当的异常处理程序,因为它处理IndexOutOfBoundsException
。因此,它被执行。
! 注意: 当我们存在多个 catch 块是,越高层的异常类应该靠后,否则会有编译错误:“java: 已捕获到异常错误”
捕获多个异常
从 Java SE 7 及更高版本开始,我们可以用一个 catch
块捕获多种类型的异常。这减少了代码重复并提高了代码的简单性和效率。
catch
块都使用竖线 |
分隔可以处理的异常类型。
它的语法是:
try {
// code
} catch (ExceptionType1 | Exceptiontype2 ex) {
// catch block
}
要了解更多信息,请访问 Java 捕获多个异常章节。
try-with-resources 语句
前面提到过,在 finally
块中关闭资源是一种很好的做法,但是经常手工关闭资源也是很繁琐的。而 try-with-resources
语句则解决了这个问题,它能帮助我们自动关闭声明的资源。
它的语法是:
try (resource declaration) {
// use of the resource
} catch (ExceptionType e1) {
// catch block
}
resource
是程序结束时要关闭的对象,它必须在 try 语句中声明和初始化。
让我们举个例子:
try (PrintWriter out = new PrintWriter(new FileWriter("OutputFile.txt")) {
// use of the resource
}
try-with-resources
语句会在语句结束后自动关闭 out
资源。
try-with-resources
语句也被称为自动资源管理。该语句会在语句结束时自动关闭所有资源。
要了解更多信息,请访问 java try-with-resources 语句。