try..catch...finally 结构中,当 try 或 catch 语句块中带有 return 时,程序的执行顺序会是什么样?
1、验证 finally 和 return 的执行顺序
1.1、try 语句正常执行
public class Circle {
public static void main(String[] args) {
int p = Circle.getint(1);
System.out.println(p);
}
public static int getint(int c) {
int a = 0;
try{
a = 6/c;
return a;
}catch(Exception e){
System.out.println("error");
return a;
}finally{
System.out.println("finally");
}
}
}
复制代码
小结:加上 debug 后进行调试,可以查看程序运行过程:
程序进入 try 后,执行到 return 时,并没有直接返回,而是又进入到 finally,然后再回到 try 语句块中的 return,最终返回。
1.2、try 语句执行异常
public class Circle {
public static void main(String[] args) {
int p = Circle.getint(0);
System.out.println(p);
}
public static int getint(int c) {
int a = 0;
try{
a = 6/c;
return a;
}catch(Exception e){
System.out.println("error");
return a;
}finally{
System.out.println("finally");
}
}
}
复制代码
小结:加上 debug 后进行调试,可以查看程序运行过程:
程序进入 try 后,遇到异常,跳转到 catch 块中,当执行到 return 时,也没有直接返回,又进入到 finally,然后再回到 catch 语句块中的 return,最终返回。
由此可见:
当 try 或 catch 块中带有 return 语句时,和没有 return 时一样,都在执行完本块所有语句后,跳转到 finally 中,当执行完 finally 语句块后,才返回最终执行结果。这样应该也是为了确保 finally 中的资源被正常关闭,不会因为 return 而出现资源被继续占用的情况。
疑问:当 finally 中对 return 的返回值进行了修改时,能否生效?
2、通过 finally 块修改返回变量
2.1、基本数据类型,try 语句正常执行
public class Circle {
public static void main(String[] args) {
int p = Circle.getint(2);
System.out.println(p);
}
public static int getint(int c) {
int a = 0;
try{
a = 6/c;
return a;
}catch(Exception e){
a = 10;
System.out.println("error");
return a;
}finally{
a = 7;
System.out.println("finally");
}
}
}
复制代码
返回结果为
finally
3
小结:虽然在 finally 中对基本数据类型的变量进行了修改,但并没有生效,最终返回的还是带有 return 语句 try 块中的执行结果。
2.2、基本数据类型,try 语句执行异常
public class Circle {
public static void main(String[] args) {
int p = Circle.getint(0);
System.out.println(p);
}
public static int getint(int c) {
int a = 0;
try{
a = 6/c;
return a;
}catch(Exception e){
a = 10;
System.out.println("error");
return a;
}finally{
a = 7;
System.out.println("finally");
}
}
}
复制代码
返回结果为
error
finally
10
小结:虽然在 finally 中对基本数据类型的变量进行了修改,但并没有生效,最终返回的还是带有 return 语句 catch 块中的执行结果。
2.3、引用数据类型,try 语句执行正常
import java.util.Arrays;
public class Circle {
public static int[] getintarr(int c) {
int[] arr = {1, 3, 5};
try{
arr[0] = 7/c;
return arr;
}catch(Exception e){
arr[0] = 10;
System.out.println("error");
return arr;
}finally{
arr[0] = 9;
System.out.println("finally");
}
}
public static void main(String[] args) {
int[] pp = Circle.getintarr(2);
System.out.println(Arrays.toString(pp));
}
}
复制代码
返回结果为
finally
[9, 3, 5]
小结:在 finally 中对引用数据类型的变量进行了修改,可以看到在最终的返回结果中,数组第一个元素是在 finally 修改的数据。
2.4、引用数据类型,try 语句执行异常
import java.util.Arrays;
public class Circle {
public static int[] getintarr(int c) {
int[] arr = {1, 3, 5};
try{
arr[0] = 7/c;
return arr;
}catch(Exception e){
arr[0] = 10;
System.out.println("error");
return arr;
}finally{
arr[0] = 9;
System.out.println("finally");
}
}
public static void main(String[] args) {
int[] pp = Circle.getintarr(0);
System.out.println(Arrays.toString(pp));
}
}
复制代码
返回结果为
error
finally
[9, 3, 5]
小结:在 finally 中对引用数据类型的变量进行了修改,可以看到在最终的返回结果中,数组第一个元素是在 finally 修改的数据。
3、结论
A、无论 try 语句是否存在 return 语句,finally 都会被执行到。
B、当 return 返回的是基本数据类型时,在 finally 中无法修改。
C、当 return 返回的是引用数据类型时,在 finally 中可以修改。
评论