在Java(以及许多其他支持异常处理的编程语言)中,try-catch-finally
结构是一种强大的错误处理机制,它允许开发者在代码中优雅地处理可能出现的运行时错误。
然而,当try
块中包含return
语句时,finally
块的执行顺序和时机可能会让初学者感到困惑。
基本概念
- try 块:用于包裹可能抛出异常的代码。
- catch 块(可选):用于捕获并处理
try
块中抛出的异常。可以有多个catch
块来捕获不同类型的异常。 - finally 块(可选):无论是否捕获到异常,
finally
块中的代码都会被执行。它主要用于执行必要的清理工作,如关闭文件、释放资源等。
当try
块中包含return
语句时,执行流程会按照以下步骤进行:
- 执行
try
块中的代码:如果try
块中的代码正常执行到return
语句,则准备返回结果。 - 执行
finally
块:在返回结果之前,finally
块中的代码会被执行。这意味着finally
块中的代码会在return
语句之后的返回值被实际返回给调用者之前执行。 - 返回结果:
finally
块执行完毕后,try
块中的return
语句的结果会被返回。
下面四类场景给大家演示下:
1. 若try{}中没有异常,则try{}中语句执行到return前一句,然后执行finally{}中的语句,最后回头执行try{}中的return语句。
public class Test1 {
public static int getA() {
int a = 5;
try {
a = 10;
System.out.println("try a = " + a);
return a; // try块中的return
} finally {
a = 20;
System.out.println("finally a =" + a);
// 注意:finally块不能改变try块中的返回值
}
}
public static void main(String[] args) {
int a = getA();
System.out.println("result a =" + a);
}
}
// 输出结果:
// try a = 10
// finally a =20
// result a =10
分析:
在Java中,finally
块中的代码不会阻止try
或catch
块中的return
语句执行,但finally
块中的代码会在return
语句之前执行(在返回值被确定之后,但在方法真正退出之前)。
然而,由于finally
块不能改变try
或catch
块中已确定的返回值(除非是通过抛出异常),所以实际上返回的是try
或catch
块中计算得到的值。
不过,为了展示流程,我们可以这样写代码,但要知道finally
块不能直接“回头”执行return
语句。
2. 如果catch{}中没有return语句,则在执行完catch{}中的代码之后就执行finally{}中的语句,最后直接结束程序,并不会回到try{}中执行它的return语句(因为没有异常,不会进入catch块)。
public class Test2 {
public static int getA() {
int a = 5;
try {
a = 10 / 0; // 除以零 故意制造异常
return a; // 这行不会执行
} catch (ArithmeticException e) {
a = 15;
System.out.println("catch a = " + a);
// 没有return语句
} finally {
a = 20;
System.out.println("finally a =" + a);
}
// 假设方法最后有一个默认的return值
return 0;
}
public static void main(String[] args) {
int a = getA();
System.out.println("result a =" + a);
}
}
// 输出结果:
// catch a = 15
// finally a =20
// result a =0
3. 如果catch{}中含有return语句,则在执行完catch{}中的return的前一语句时直接进入finally{}中执行代码,但finally块中的代码不会改变catch块中已确定的返回值。
public class Test3 {
public static int getA() {
int a = 5;
try {
a = 10 / 0; // 故意制造异常
return a; // 这行不会执行
} catch (ArithmeticException e) {
a = 15;
System.out.println("catch a = " + a);
return a; // catch块中的return
} finally {
a = 20;
System.out.println("finally a =" + a);
// 注意:finally块不会改变catch块中的返回值
}
// 这部分代码不会执行
}
public static void main(String[] args) {
int a = getA();
System.out.println("result a =" + a);
}
}
// 输出结果:
// catch a = 15
// finally a =20
// result a =15
4. 如果finally中有return,那么最后的结果一定是finally中的return结果(不管有没有异常)。
public class Test4 {
public static int getA() {
int a = 5;
try {
a = 10;
System.out.println("try a = " + a);
return a; // try块中的return,但会被finally中的return覆盖
} catch (Exception e){
a = 15;
System.out.println("catch a = " + a);
return a; // catch块中的return,但同样会被finally中的return覆盖
} finally {
a = 20;
System.out.println("finally a =" + a);
return a; // finally块中的return,这会覆盖try和catch中的return
}
}
public static void main(String[] args) {
int a = getA();
System.out.println("result a =" + a);
}
}
// 输出结果:
// try a = 10
// finally a =20
// result a =20