写点什么

面试被问 finally 和 return,到底谁先执行?

用户头像
Damon
关注
发布于: 2021 年 05 月 09 日

经常有人面试被问到,finally 和 return,到底谁先执行呢?

为了解决这个问题,其实我们可以先想想 finally 是被用来干嘛的呢?它是被用来结束一些正常的收尾动作或结束标识。也就是说无论怎么样,finally 都会被最后执行。例如:一般在操作数据库时,用 Jdbc 连接池连接数据库后释放资源,需要 finally 来处理。再如 redis 连接,在获取连接池处理完数据的增删改查后,需要释放其连接池。

但是,如果 return 是在 finally 前面呢?或者在 finally 后面呢?我们先来看看 return 在 finally 前面时,如:

package com.test;
/** * * * @author Damon * @date 2020年3月18日 上午11:02:08 * */public class App {  public static void main(String[] args) {    System.out.println("return result: " + test());  }
  public static int test() {    try {      Thread.sleep(1);      System.out.println("執行 return 1");      return 1;// return 在try里,則先執行,再執行finally后才有可能执行该return    }    catch (InterruptedException e) {      e.printStackTrace();      return -1;    }    finally {      System.out.println("执行 finally");      //return 3;    }    //System.out.println("執行 return 2");    //return 1;  }}
结果:
執行 return 1执行 finallyreturn result: 1

复制代码

也就是说,在执行 return 之前,先执行了 finally。

我们在看,如果 finally 前面有 return,在其内部也有 return:

package com.test;
/** * * * @author Damon * @date 2020年3月18日 上午11:02:08 * */public class App {  public static void main(String[] args) {    System.out.println("return result: " + test());  }
  public static int test() {    try {      Thread.sleep(1);      System.out.println("執行 return 1");      return 1;// return 在try里,則先執行,再執行finally后才有可能执行该return    }    catch (InterruptedException e) {      e.printStackTrace();      return -1;    }    finally {      System.out.println("执行 finally");      return 3;    }    //System.out.println("執行 return 2");    //return 1;  }}
结果:
執行 return 1执行 finallyreturn result: 3

复制代码

其内部被 return 后,就不再执行前面那个 return 了。


我们再来看 return 在 finally 之后,如:

package com.test;
/** * * * @author Damon * @date 2020年3月18日 上午11:02:08 * */public class App {  public static void main(String[] args) {    System.out.println("return result: " + test());  }
  public static int test() {    try {      Thread.sleep(1);      //System.out.println("執行 return 1");      //return 1;// return 在try里,則先執行,再執行finally后才有可能执行该return    }    catch (InterruptedException e) {      e.printStackTrace();      //return -1;    }    finally {      System.out.println("执行 finally");      //return 3;    }    System.out.println("執行 return 2");    return 1;  }}
结果:
执行 finally執行 return 2return result: 1

复制代码

总结:finally 在 return 之后时,先执行 finally 后,再执行该 return;finally 内含有 return 时,直接执行其 return 后结束;finally 在 return 前,执行完 finally 后再执行 return。

接下来还有常被问到的是:Java 中 final、finally、finalize 的区别与用法:

  • final 用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,类不可继承。即如果一个类被声明为 final,意味着它不能作为父类被继承,因此一个类不能同时被声明为 abstract 的,又被声明为 final 的。变量或方法被声明为 final,可以保证它们在使用中不被修改。被声明为 final 的变量必须在声明时给赋予初值,而在以后的引用中只能读取,不可修改。被声明为 final 的方法也同样只能使用,不能重载。

  • finally 是异常处理语句结构的一部分,总是执行,常见的场景:释放一些资源,例如前面所说的 redis、db 等。在异常处理时提供 finally 块来执行任何清除操作,即在执行 catch 后会执行 finally 代码块。

  • finalize 是 Object 类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,可以覆盖此方法提供垃圾收集时的其他资源回收,例如关闭文件等。

结束福利

开源实战利用 k8s 作微服务的架构设计代码:

https://gitee.com/damon_one/spring-cloud-k8shttps://gitee.com/damon_one/spring-cloud-oauth2
复制代码

欢迎大家 star,多多指教。

关于作者

  笔名:Damon,技术爱好者,长期从事 Java 开发、Spring Cloud 的微服务架构设计,以及结合 Docker、K8s 做微服务容器化,自动化部署等一站式项目部署、落地。目前主要从事基于 K8s 云原生架构研发的工作。Golang 语言开发,长期研究边缘计算框架 KubeEdge、调度框架 Volcano 等。公众号 程序猿Damon 发起人。个人微信 MrNull008,个人网站:Damon | Micro-Service | Containerization | DevOps,欢迎來撩。

欢迎关注:InfoQ

欢迎关注:腾讯自媒体专栏


精彩推荐

欢迎关注




发布于: 2021 年 05 月 09 日阅读数: 19
用户头像

Damon

关注

God bless the fighters. 2020.03.11 加入

欢迎关注公众号:程序猿Damon,长期从事Java开发,研究Springcloud的微服务架构设计。目前主要从事基于K8s云原生架构研发的工作,Golang开发,长期研究边缘计算框架KubeEdge、调度框架Volcano、容器云KubeSphere研究

评论

发布
暂无评论
面试被问finally 和 return,到底谁先执行?