当try、catch中有return时,finally中的代码会执行么?

今天,看到一个面试题:

try-catch-finally 中,如果 catch 中 return 了,finally 还会执行吗?

我们用代码来验证下:

    public static void main(String[] args) {
        System.out.println("我是输出结果a:" + test1());
        

    public static int test1() {
        int a = 5;
        try {
            System.out.println(a / 0);
            a = 10;
        } catch (ArithmeticException e) {
            System.out.println("我是catch中的a:" + a);
            return a = 20;// 程序执行到这时,a=20已经执行完,准备好返回结果了,发现有finally,则在去执行finally
        } finally {
            System.out.println("我是finally中未重定义的a:" + a);
            a = 30;
            System.out.println("我是finally中重定义过的a:" + a);
        }
        return a;
    }

运行结果:

1 我是catch中的a:5
2 我是finally中未重定义的a:20
3 我是finally中重定义过的a:30
4 我是输出结果a:20

从结果中可看出:即使catch中return了,finally中的代码还是会执行。但是有个问题,明明结果显示,经过finally代码的执行,a已经是30了,返回结果为什么还是20?

我们再执行另外代码:

 1     public static void main(String[] args) {
 2         System.out.println("我是输出结果a:" + test1());
 3         
 4     }
 5 
 6     public static int test1() {
 7         int a = 5;
 8         try {
 9             System.out.println(a / 0);
10             a = 10;
11         } catch (ArithmeticException e) {
12             System.out.println("我是catch中的a:" + a);
13             return a = 20;// 程序执行到这时,a=20已经执行完,准备好返回结果了,发现有finally,则在去执行finally
14         } finally {
15             System.out.println("我是finally中未重定义的a:" + a);
16             a = 30;
17             System.out.println("我是finally中重定义过的a:" + a);
18             return a = 30;
19         }
20     }

运行结果:

1 我是catch中的a:5
2 我是finally中未重定义的a:20
3 我是finally中重定义过的a:30
4 我是输出结果a:30

我们会发现,如果finally中有return,结果会根据finally中的结果返回,如果finally中没有return,结果会按照catch的结果返回,但是不管怎么样,都是会执行finally的代码。

前面的例子是基本类型的,那我们看下引用类型是不是也这样:

 1     public static User getName1(){
 2         User user = null;
 3         try {
 4             user = new User("张三");
 5             throw new Exception();
 6         } catch (Exception e) {
 7             user = new User("李四");
 8             return user;
 9         } finally {
10             user = new User("王五");
11             //return user;
12         }
13     }

结果

User [name=李四]

再试下其他:

 1     public static User getName1(){
 2         User user = null;
 3         try {
 4             user = new User("张三");
 5             throw new Exception();
 6         } catch (Exception e) {
 7             user = new User("李四");
 8             return user;
 9         } finally {
10             user = new User("王五");
11             return user;
12         }
13     }

结果:

1 User [name=王五]

额。。。。。。引用类型类型好像也是这样的。

我们再看看:

 1     public static User getName2(){
 2         User user = null;
 3         try {
 4             user = new User("张三");
 5             throw new Exception();
 6         } catch (Exception e) {
 7             user.setName("李四");
 8             return user;
 9         } finally {
10             user.setName("王五");
11             //return user;
12         }
13     }

结果如下:

User [name=王五]

额。。。。好像不对啊,不应该是李四吗?

 1     public static User getName2(){
 2         User user = null;
 3         try {
 4             user = new User("张三");
 5             throw new Exception();
 6         } catch (Exception e) {
 7             user.setName("李四");
 8             return user;
 9         } finally {
10             user.setName("王五");
11             return user;
12         }
13     }

结果:

User [name=王五]

引用类型好像有问题啊。。。。

其实可以这么理解:执行完catch内的代码后,会把结果值暂时保存,然后执行finally中的代码,如果finally中没有return,则直接把保存的值返回。如果finally中有return,则值会被finally改变,再返回。

而如果finally中没有return,返回的值好像也有部分出乎我们的意料。可以这样理解吧,catch中的结果值会被final修饰,当final修饰一个基本数据类型时,表示该基本数据类型的值一旦在初始化后便不能发生变

化;如果final修饰一个引用类型时,则在对其初始化之后便不能再让其指向其他对象了,但该引用所指向的对象的内容是可以发生变化的。

就那下面代码来说明:

1 User u1 = new User("张三");
2 User u2 = new User("李四");
3 final User u3  = u1;
4 u3 = u2;//这行代码会报编译错误
5 System.out.println(u3);
6 u1.setName("王五");
7 System.out.println(u3);

第四行代码会报编译错误:The final local variable u3 cannot be assigned. It must be blank and not using a compound assignment

说明final修饰的不能改变引用对象,但是引用对象u1的值变化还是可以。

上面的代码执行下:

User [name=张三]
User [name=王五]

现在可以看出 上面的代码  user.setName("王五");和user = new User("王五"); 执行的结果为什么会不一样,因为setname改变的是引用所指向的对象的内容,是可以的。= new User("王五"); 是改变了引用指向,是不可以的。

原文地址:https://www.cnblogs.com/xiaojiesir/p/11385981.html