try...catch...finally与返回值的问题
面试过程中,面试官经常会问一下代码细节的问题,比如在try...catch...finally都有return语句,那么那个代码块中的return会生效呢?又比如在try中返回一个值a,finally中修改这个值,那么返回的a是finally中修改过的还是没有修改过的呢?下面我们通过几组案例来分析下有关try...catch...finally中返回值的问题。
注意:无论发生什么情况,finally中的语句是一定会执行的
案例1:try代码块中发生异常时候,哪个部分的return会执行呢?
测试代码
public class TryCatchDemo {
public static void main(String[] args) {
System.out.println(tryCatchTest());
}
public static int tryCatchTest() {
try {
//制造异常,设置return语句
int a = 3/0;
return 1;
}catch (Exception e) {
//捕捉异常,并在catch设置了return语句
System.out.println("捕捉的异常了");
return 2;
}finally {
//在finally中设置返回语句
System.out.println("finally执行了");
return 3;
}
}
}
运行结果
结果分析
最后的返回值是finally中的return语句的值,在try中发生了异常之后,异常之后的语句就不会再执行了,也就是说try中的return语句没有执行,catch中虽然有return语句,但是finally中代码是一定会执行的,所以在catch中return语句执行前执行了finally中的语句,所以最后返回的是3。假设这里没有finally,那么返回的是2,也就是catch中的return
案例2:try中没有发生异常,哪个部分的return会执行呢?
测试代码
public class TryCatchDemo {
public static void main(String[] args) {
System.out.println(tryCatchTest());
}
public static int tryCatchTest() {
try {
//设置return语句
return 1;
}catch (Exception e) {
//捕捉异常,并在catch设置了return语句
System.out.println("捕捉的异常了");
return 2;
}finally {
//在finally中设置返回语句
System.out.println("finally执行了");
return 3;
}
}
}
运行结果
结果分析
返回的结果依然是finally中的值,finally中的语句是一定会执行的,所以在try中的return语句执行之前,去执行了finally中的语句,而fianlly中有return语句,所以最后返回的是3。
案例3:设置一个基本类型的变量,finally中修改该变量的值,try中返回该变量,那么最终返回的变量的值是多少呢?
测试代码
public class TryCatchDemo {
public static void main(String[] args) {
System.out.println(tryCatchTest());
}
public static int tryCatchTest() {
//设置返回值
int a = 1;
try {
return a;
}finally {
//改变返回值
System.out.println("finally执行了");
a = 3;
}
}
}
运行结果
结果分析
虽然在finally中a=3
修改了a的值,但是最后依然返回的是1,说明try中在return之前将返回值保存了起来,finally中的修改并没有生效。
案例4:设置一个引用类型的变量,finally中修改该变量的值,try中返回该变量,那么最终返回的变量的值是多少呢?
测试代码
public class TryCatchDemo {
public static void main(String[] args) {
System.out.println(tryCatchTest().getName());
}
public static Child tryCatchTest() {
//创建对象实例并设置初始name
Child child = new Child("张三");
try {
return child;
}finally {
//修改对象中的name
System.out.println("finally执行了");
child.setName("李四");
}
}
}
//设置又给对象
class Child {
private String name;
public Child(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
运行结果
结果分析
因为变量是引用数据类型,变量相当于是对象的地址,在finally中的修改实际上修改了对象中的值,所以对于引用数据类型,finally中的修改会生效。
总结
- finally中的语句是一定会执行的,所以如果finally中有return语句,那么程序会在finally中返回
- 如果finally中没有return语句,执行完finally会去执行try或者catch中的return,如果没发生异常,则执行try中的return,如果发生了异常,那么执行catch中的return
- 对于基本类型或者字符串,在finally中的修改并不起作用,try中的return返回值仍然是再进入finally之前保存的值。
- 对于引用类型的数据,在finally中的修改会起作用,try中return返回值是finally修改后的值。