本篇文章我们主要探讨 一下如果try {}语句中有return,这种情况下finally语句还会执行吗?其实JVM规范是对这种情况有特殊规定的,那我就先上代码吧!

public class FinallyTest {
public int method() {
int x = 1;
try{
++ x;
return x;
}catch(Exception e){ }finally{
++ x;
}
return x;
} public static void main(String[] args) {
FinallyTest t = new FinallyTest();
int y = t.method();
System.out.println(y);
}
}

对于上述代码,我们有以下几个问题,来自测一下吧:

  1. 如果在 try 语句块里使用 return 语句,那么 finally 语句块还会执行吗?

  2. 如果执行,那么是怎样实现既执行 return 又执行 finally 的呢?

  3. 上面的程序输出是什么?为什么?

finally 语句块还会执行吗

对于该问题,答案是肯定的。Java官方文档上是这么描述的:

The finally block always executes when the try block exits.`

我们看到描述词用的是always,即在try执行完成之后,finally是一定会执行的。这种特性可以让程序员避免在try语句中使用了return, continue或者 break关键字而忽略了关闭相关资源的操作。把清理相关资源放到finally语句块中一直是最佳实践。

PS: 用到finally关闭资源的时候,给大家提个醒,应该尽量避免在finally语句块中出现运行时错误,可以适当添加判断语句以增加程序健壮性:

finally {
if (out != null) {
System.out.println("Closing PrintWriter");
out.close(); // 不要在finally语句中直接调用close()
} else {
System.out.println("PrintWriter not open");
}
}

try { return } finally{}?

我们知道了finally语句会执行,当我们在IDE上运行该程序的时候,会发现运行结果是2。那么为什么不是3呢?

我们来debug一下:

我们在下图可以看到,try中x值是2,且执行了try语句块中的return x语句。

之后执行了finally语句,x重新赋值为3`。

try中返回了x=2, finally语句又重新设置了x=3,为什么返回给主程序的结果是2呢?

原来JVM规范里面明确说明了这种情况:

If the try clause executes a return, the compiled code does the following:

1. Saves the return value (if any) in a local variable.
2. Executes a jsr to the code for the finally clause.
3. Upon return from the finally clause, returns the value saved in the local variable.

大意就是如果在try中return的情况下,先把try中将要return的值先存到一个本地变量中,即本例中的x=2将会被保存下来。接下来去执行finally语句,最后返回的是存在本地变量中的值,即返回x=2.

Notes:还有一点要注意的,如果你在finally里也用了return语句,比如return ++x。那么程序返回值会是3。因为规范规定了,当try和finally里都有return时,会忽略try的return,而使用finally的return。

总结

今天主要介绍了当try语句中有return的时候,其与finally语句的执行情况。我们的得到的结论有:

  1. try中有return, 会先将值暂存,无论finally语句中对该值做什么处理,最终返回的都是try语句中的暂存值。
  2. 当try与finally语句中均有return语句,会忽略try中return。

本文由博客一文多发平台 OpenWrite 发布!

文章首发:https://zhuanlan.zhihu.com/lovebell

个人公众号:技术Go

您的点赞与支持是作者持续更新的最大动力!

【搞定面试官】try中有return,finally还会执行吗?的更多相关文章

  1. 搞定面试官 - 你可以介绍一下在 MySQL 中,哪些情况下 索引会失效嘛?

    大家好,我是程序员啊粥,前边给大家分享了 *MySQL InnoDB 索引模型 在 MySQL InnoDB 中,为什么 delete 删除数据之后表数据文件大小没有变 如何计算一个索引的长度 如何查 ...

  2. 搞定面试官 - MySQL 中你知道如何计算一个索引的长度嘛?

    大家好,我是程序员啊粥. 今天给大家分享一个我遇到过的比较少见的面试题,那就是 MySQL 中如何计算一个索引的长度. 说实话,我第一次遇到这个问题的时候想当然的以为索引长度就是我们建表时定义的字段长 ...

  3. 金三银四,2018最新iOS面试题,由它可以搞定面试官?

    序言 这些资料,你一定会用到!我相信很多人都在说,iOS行业不好了,iOS现在行情越来越难了,失业的人比找工作的人还要多.失业即相当于转行,跳槽即相当于降低自己的身价.那么做iOS开发的你,你是否在时 ...

  4. 【搞定面试官】你还在用Executors来创建线程池?会有什么问题呢?

    前言 上文我们介绍了JDK中的线程池框架Executor.我们知道,只要需要创建线程的情况下,即使是在单线程模式下,我们也要尽量使用Executor.即: ExecutorService fixedT ...

  5. 【搞定面试官】谈谈你对JDK中Executor的理解?

    ## 前言 随着当今处理器计算能力愈发强大,可用的核心数量越来越多,各个应用对其实现更高吞吐量的需求的不断增长,多线程 API 变得非常流行.在此背景下,Java自JDK1.5 提供了自己的多线程框架 ...

  6. 【搞定面试官】- Synchronized如何实现同步?锁优化?(1)

    前言 说起Java面试中最高频的知识点非多线程莫属.每每提起多线程都绕不过一个Java关键字--synchronized.我们都知道该关键字可以保证在同一时刻,只有一个线程可以执行某个方法或者某个代码 ...

  7. 搞定面试官:咱们从头到尾再说一次 Java 垃圾回收

    接着前几天的两篇文章,继续解析JVM面试问题,送给年后想要跳槽的小伙伴 万万没想到,面试中,连 ClassLoader类加载器 也能问出这么多问题..... 万万没想到,JVM内存区域的面试题也可以问 ...

  8. RabbitMQ:从入门到搞定面试官

    安装 使用docker安装,注意要安装tag后缀为management的镜像(包含web管理插件),我这里使用的是rabbitmq:3.8-management 1. 拉取镜像 shell docke ...

  9. 搞定面试官 - 可以介绍一下在 MySQL 中你平时是怎么使用 COUNT() 的嘛?

    大家好,我是程序员啊粥. 相信在大家的工作中,有很多的功能都需要用到 count(*) 来统计表中的数据行数.同时,对于一些大数据的表,用 count 都是瑟瑟发抖,往往会结合缓存等进行处理. 那么, ...

随机推荐

  1. 爬虫之scrapy简单案例之猫眼

    在爬虫py文件下 class TopSpider(scrapy.Spider): name = 'top' allowed_domains = ['maoyan.com'] start_urls = ...

  2. 死磕 java线程系列之终篇

    (手机横屏看源码更方便) 简介 线程系列我们基本就学完了,这一个系列我们基本都是围绕着线程池在讲,其实关于线程还有很多东西可以讲,后面有机会我们再补充进来.当然,如果你有什么好的想法,也可以公从号右下 ...

  3. Python基本数据结构之字典

    定义: {key1:value1,key2:value2} 1.键与值用冒号“:”分开: 2.项与项用逗号“,”分开: 示例: dic4={ 'name': 'xiaohu', 'age': 20, ...

  4. 数组去重(高效率,ES6才支持)

    //数组去重 function distinct(arr) { let result = []; let obj = {}; for(let i of arr) { if(!obj[i]) { res ...

  5. fcgi-2.4.1.tar.gz 和 spawn-fcgi-1.6.4.tar.gz 百度云

    链接:https://pan.baidu.com/s/1nEzOkFC0-rfVMDy_BygLWg 提取码:ty0e 美好的东西都是免费滴

  6. HTML——基础知识点1

  7. springboot~高并发下耗时操作的实现

    高并发下的耗时操作 高并发下,就是请求在一个时间点比较多时,很多写的请求打过来时,你的服务器承受很大的压力,当你的一个请求处理时间长时,这些请求将会把你的服务器线程耗尽,即你的主线程池里的线程将不会再 ...

  8. maven打包记录1

    在需要打包的项目目录下找到pom.xml文件 (过程中可能遇到 :-Dmaven.multiModuleProjectDirectory system property is not set. Che ...

  9. Oracle基础:数据库操作_数据库事务_表的锁定

    数据库操作语句: INSERT INTO 表名[(字段列表)] VALUES ( 表达式列表); 例子:INSERT INTO emp(empno,ename,job,hiredate) VALUES ...

  10. 大学生活这样过,校招 offer 飞来找

    01.开门见山 由于我比较喜欢分享的原因,认识了不少大学生.其中有不少佼佼者,比如说一年读 50 本书的璐璐,校招斩获一线大厂 Offer 的晓峰,通过运营公众号实现经济独立的帅土. 当然也有一些不知 ...