Java中finally和return的执行关系
Java中的finally
关键字可以分为两方面理解:
finally
的执行时机问题。finally
总会执行(除非在finally
代码块之前System.exit()
语句被执行了)。正常情况下finally
代码块在try
代码块执行完毕之后被执行,出现异常时在catch
代码块执行完毕后被执行。- 返回值问题。可以认为
try
代码块(或者catch
代码块)中的return
语句的返回值被放在线程栈的顶部:如果返回值是基本类型则顶部存放的就是值,如果返回值是引用类型,则顶部存放的是引用。可以在finally
代码块中修改栈顶中引用类型所对应的对象的内容,却无法修改栈顶中的基本类型。但不管栈顶中存放的是基本类型还是引用类型,都可以被finally
中return
语句的“具体值”覆盖。
不建议在finally中使用return语句,如果有,IntelliJ IDEA 会 警告:
Reports return statements inside of finally blocks. While occasionally intended, such return statements may mask exceptions thrown, and tremendously complicate debugging.
public class FinallyTest {
public static void main(String[] args) {
System.out.println(test());
System.out.println(testPrimitive());
}
public static Student test() {
Student result = new Student("Tom", 0);
try {
result.setAge(1);
return result;
} catch (Exception e) {
result.setAge(2);
return result;
} finally {
result.setAge(3); //引用类型的返回值,可被修改(即实际上会修改栈顶所引用的对象的内容)
//return new Student("Kobe", 33); //如果去掉这行注释,那么最终返回值会变为"Kobe"
}
}
public static int testPrimitive() {
int x = 0;
try {
x = 1;
return x;
} catch (Exception e) {
x = 2;
return x;
} finally {
x = 3; //基本类型的返回值,不可被修改(即修改x不会对栈顶造成影响)。最终返回值仍然是 1
//return x; //如果去掉这一行注释,那么最终返回值为 3
}
}
private static class Student {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
public void setAge(int age) {
this.age = age;
}
}
}