Java 的 try 、catch、finally 代码块有助于编写可能导致程序出现异常的代码。
try 代码块
try 代码块包含应在正常条件下运行的应用程序代码。 例如,读取文件,写入数据库或执行复杂的业务操作。
try {
//业务代码
}
catch 代码块
catch 位于 try 之后,并且必须处理 try 中引发的受检异常以及任何可能的非受检异常。
try {
//业务代码
}
catch(Exception e) {
//异常处理
}
应用程序可能出现多种不同类型的异常,我们可以通过多个 catch 代码块来处理这些不同的异常。
在每个 catch 代码中,都可以有不同的处理方式:
try {
//业务代码
}
catch(NullPointerException e) {
//异常处理1
}
catch(NumberFormatException e) {
//异常处理2
}
catch(Exception e) {
//异常处理3
}
这些异常处理逻辑只会执行其中一个。从上到下,只要任意一个异常属于当前程序异常或者异常的父类,都会直接进入该 catch 块,而不会进入接下来的异常处理。
有时候,我们对所有可能的异常都有相同的处理逻辑,可以简化:
try {
//业务代码
}
catch(NullPointerException | NumberFormatException e) {
//异常处理
}
finally 代码块
finally 代码块可以保证代码一定能被执行,即使程序出现错误,我们也希望能做某些善后工作,防止出现更糟糕的情况。
try {
//文件操作
}
catch(IOException e) {
//文件操作异常处理
}
finally {
//关闭文件
}
当然,也可不不处理异常,因为它不是必须的:
try {
//文件操作
}
finally {
//关闭文件
}
不过需要注意的是,无论怎样,try 都是必须的。
异常运行机制
当程序发生异常时,JVM 将错误信息包装在 Throwable 子类型的实例中。此异常对象类似于其他 Java 对象,具有字段和方法唯一的区别是 JVM 检查它们的存在并将控制权传递给catch块。
执行流程
如果没有发生异常,那么 JVM 将仅执行finally块,catch块将被跳过。
如果try块中发生异常,则 JVM 将首先执行catch块,然后执行finally。
try-with-resources
对于可关闭的资源(例如流),Java SE 7 引入了try-with-resources语句,这是在上述情况下处理异常的推荐方法。 在这种方法中,我们不需要关闭流,而 JVM 会为我们完成它。
在try-with-resources中,资源在小括号内的try代码块中声明,finally 块完全消失了。
try (BufferedReader br = new BufferedReader(new FileReader(fileName))){
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}