需要知道的是:finally的语句会先于try或者catch的返回语句之前执行,如果finally中有return语句,那么try或catch中的return语句会被finally中的return覆盖,不建议在finally中放return
情况一:try、catch和finally中都有return
public static void main(String[] args) {
System.out.println(testInt());
}
private static int testInt(){
int a = 0;
try{
return a;
}catch (Exception e){
a = 9;
e.printStackTrace();
return a;
}finally {
a = 10;
return a;
}
}
最后输出:
10
在try中的return执行之前,会执行finally中的语句,finally中有return,于是会覆盖掉try中的return。如果此时发生了异常,catch中的return语句会执行吗?看下面:
public static void main(String[] args) {
System.out.println(testInt());
}
private static int testInt(){
int a = 0;
try{
int b = 7/a; //产生了异常
return a;
}catch (Exception e){
a = 9;
e.printStackTrace();
return a;
}finally {
a = 10;
return a;
}
}
输出结果:
10
java.lang.ArithmeticException: / by zero
at pattern.App.testInt(App.java:40)
at pattern.App.main(App.java:31)
产生了异常,catch中语句被执行,但是catch中的return执行之前会执行finally中的语句,所以catch中的return依然被覆盖
情况二:try或者catch中有return,finally中没有return
public static void main(String[] args) {
System.out.println(testInt());
}
private static int testInt(){
int a = 0;
try{
return a;
}catch (Exception e){
a = 9;
e.printStackTrace();
return a;
}finally {
System.out.println("执行finally");
a = 10;
}
}
输出:
执行finally
0
可以看到,finally中的语句依然执行了,但是a的值在finally中改变了,返回值并没有改变,如果这里产生了异常呢?自然是会输出9的(可以自己验证一下),这里可以看到对于基本类型a,finally的赋值并没有改变返回值,如果是下面非基本类型的情况呢?
情况三:对于非基本类型
public static void main(String[] args) {
System.out.println(testNum().getNum());
}
private static Num testNum(){
Num num = new Num();
int a = 0;
try{
num.setNum(7);
return num;
}catch (Exception e){
e.printStackTrace();
num.setNum(9);
}finally {
num.setNum(10);
}
return num;
}
最后输出结果:
10
同理如果是产生了异常,结果仍然是10(可以自己验证)
可以看到,对于非基本类型,finally中的赋值最后在return中会被返回,通过看向志明《深入理解Java虚拟机》第187页讲解“class文件的属性表”的时候,找到了为什么:
- 不管什么情况,finally中的语句总会执行(除非程序执行System.exit()),正常情况下载try后面执行,抛异常时载catch后面执行
- 对于返回值问题。try(或者catch)中的return语句的返回值放入线程栈的顶部:如果返回值是基本类型则顶部存放的就是值,如果返回值是引用类型,则顶部存放的就是地址。finally中的return语句可以修改引用所对应的对象,无法修改基本类型。所以情况二中的基本类型finally无法修改,但是情况三可以修改
- 不建议在finally中使用return