return 和 finally 谁先执行
# return 和 finally 谁先执行
本文聊聊 try 或 catch 块中,如果有了 return,那么是 return 先执行还是 finally 先呢?
# 分类讨论
假设 try 块中有 return 语句,try 语句在返回前,将其他所有的操作执行完,保留好要返回的值,而后转入执行 finally 中的语句。分为以下情况:
情况一:如果 finally 中有 return 语句,则会将 try 中的 return 语句”覆盖“掉,直接执行 finally 中的 return 语句,得到返回值,这样便无法得到 try 之前保留好的返回值。
情况二:如果 finally 中没有 return 语句,也没有改变要返回值,则执行完 finally 中的语句后,会接着执行 try 中的 return 语句,返回之前保留的值。
情况三:如果 finally 中没有 return 语句,但是改变了要返回的值,这里有点类似与引用传递和值传递的区别,分以下两种情况:
- 1)如果 return 的数据是基本数据类型或文本字符串,则在 finally 中对该基本数据的改变不起作用,try 中的 return 语句依然会返回进入 finally 块之前保留的值。
- 2)如果 return 的数据是引用数据类型,而在 finally 中对该引用的成员变量的改变起作用,因为返回的是引用,引用是没有变的,但引用里面的成员变量被改变了
特殊情况:在 try 里面有
System.exit(0)
这样的语句,System.exit(0)
是终止 Java 虚拟机 JVM 的,连 JVM 都停止了,一切都结束了,也就不存在返回值给调用者的情况
# 情况一
finally 中有 return 语句,会将 try 中的 return 语句”覆盖“。测试代码:
/* 情况一:如果finally中有return语句,则会将try中的return语句”覆盖“掉,
直接执行finally中的return语句,得到返回值,这样便无法得到try之前保留好的返回值。
*/
public static int testCase1(){
int number = 100;
try{
System.out.println("testCase1 try语句块执行中... ");
number += 100;
return number;
}catch (Exception e){
e.printStackTrace();
}finally {
System.out.println("testCase1 finally语句块执行中...");
number = 500;
return number;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
执行结果:
System.out.println("testCase1返回:" + testCase1()); //500
# 情况二
如果 finally 中没有 return 语句,也没有改变要返回值,则执行完 finally 中的语句后,会接着执行 try 中的 return 语句。测试代码:
/**
* 情况二:如果finally中没有return语句,也没有改变要返回值,
* 则执行完finally中的语句后,会接着执行try中的return语句,返回之前保留的值。
* @return
*/
public static int testCase2(){
int number = 100;
try{
System.out.println("testCase2 try语句块执行中... ");
number += 100;
return number;
}catch (Exception e){
e.printStackTrace();
}finally {
System.out.println("testCase2 finally语句块执行中...");
}
return 10;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
执行结果:
System.out.println("testCase2返回:" + testCase2()); //200
# 情况三
如果 finally 中没有 return 语句,但是改变了要返回的值,这里有点类似与引用传递和值传递的区别,分以下两种情况:
- 1)如果 return 的数据是基本数据类型或文本字符串,则在 finally 中对该基本数据的改变不起作用,try 中的 return 语句依然会返回进入 finally 块之前保留的值。
- 2)如果 return 的数据是引用数据类型,而在 finally 中对该引用的成员变量的改变起作用,因为返回的是引用,引用是没有变的,但引用里面的成员变量被改变了
# 3.1
/**
* 情况三:如果finally中没有return语句,但是改变了要返回的值,并且返回的是基本数据类型,则改变不会生效
* @return
*/
public static int testCase3(){
int number = 100;
try{
System.out.println("testCase3 try语句块执行中... ");
number += 100;
return number;
}catch (Exception e){
e.printStackTrace();
}finally {
System.out.println("testCase3 finally语句块执行中...");
number = 500;
}
return 10;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
运行结果:
System.out.println("testCase3返回:" + testCase3()); //200
# 3.2
/**
* 情况三:如果finally中没有return语句,但是改变了要返回的值,并且返回的是引用数据类型,则改变会生效
* @return
*/
public static Num testCase3_2(){
Num number = new Num();
try{
System.out.println("testCase3_2 try语句块执行中... ");
return number;
}catch (Exception e){
e.printStackTrace();
}finally {
System.out.println("testCase3_2 finally语句块执行中...");
number.num = 100;
}
return number;
}
class Num{
public int num = 1;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
运行结果:
System.out.println("testCase3_2返回:" + testCase3_2().num); //200
# 总结
即使在 try 或 catch 代码块中有 return 语句,也会执行 finally 语句,但是 finally 能否改变返回的值,取决于 return 后的内容是否为引用类型,如果是则引用的成员变量可以发生改变,如果为基本数据类型,则不可发生改变。
参考:
return 和 finally 谁先执行_先 return 还是先 finally_醺泽的博客-CSDN 博客 (opens new window)
try catch 语句中有 return 的各类情况_hello_world_he 的博客-CSDN 博客 (opens new window)