zoukankan      html  css  js  c++  java
  • 当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("王五"); 是改变了引用指向,是不可以的。

  • 相关阅读:
    Atitit.执行cli cmd的原理与调试
    Atitit. IE8.0 显示本地图片预览解决方案 img.src=本地图片路径无效的解决方案
    SlidingDrawer的简单实例(抽屉效果)
    Android android.intent.category解析
    layout中加载gif图片
    Java 中 Vector、ArrayList、List 使用深入剖析
    定时器的简单实例
    supportsscreens
    Android屏幕元素层次结构
    panel的抽屉效果
  • 原文地址:https://www.cnblogs.com/xiaojiesir/p/11385981.html
Copyright © 2011-2022 走看看