专栏首页国产程序员你真的了解try{ return }finally{}中的return?

你真的了解try{ return }finally{}中的return?

先看一段程序

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

你觉得输出是2还是3.

我刚开始看的时候以为输出是3.但是看了之后的解释,感觉自己基础真的是不扎实。

官方的解释是这样的:

The finally Block

The finally block always executes when the try block exits. This ensures that the finally block is executed even if an unexpected exception occurs. But finally is useful for more than just exception handling — it allows the programmer to avoid having cleanup code accidentally bypassed by a return, continue, or break. Putting cleanup code in a finally block is always a good practice, even when no exceptions are anticipated.

Note: If the JVM exits while the try or catch code is being executed, then the finally block may not execute. Likewise, if the thread executing the try or catch code is interrupted or killed, the finally block may not execute even though the application as a whole continues.

什么意思?简单翻译一下:

当try语句退出时肯定会执行finally语句。这确保了即使发了一个意想不到的异常也会执行finally语句块。但是finally的用处不仅是用来处理异常——它可以让程序员不会因为return、continue、或者break语句而忽略了清理代码。把清理代码放在finally语句块里是一个很好的做法,即便可能不会有异常发生也要这样做。

注意,当try或者catch的代码在运行的时候,JVM退出了。那么finally语句块就不会执行。同样,如果线程在运行try或者catch的代码时被中断了或者被杀死了(killed),那么finally语句可能也不会执行了,即使整个运用还会继续执行。

从上面的官方说明,我们知道无论try里执行了return语句、break语句、还是continue语句,finally语句块还会继续执行

继续看代码,我们用debug跑一下:

执行下一步:

当前x的值是1,下一步:

这一步跳到finally,现在的x=2,说明执行了try块中的 ++x,下一步:

又跳回try块中的return,当前的x=3.

走到这你是不是也跟我一样以为输出是3了。接着看:

最后的输出是2.

是不是有些疑惑

从上面过程中可以看到:

try 里 使用 return 还是会执行finally语句的(我们用debug的模式看到了程序会跳到 finally语句里执行)执行完finally语句才执行 return。为什么?从上面

的图可以合理推理出return +xx;是分开来执行的,先执行++x,再执行finally,最后才执行return跳出函数。因为程序调两次跳到了 return +xx; 语句上。(其实要验证 return ++x 是分开两部分执行的方法很简单,把变量x变成static变量并在main函数里输出,会发现x的值还是3,即使两次跳到 return ++x 也只是第一次执行了加1操作,第二次只是执行了return而没有执行++x。这里是合理推理,后面有真凭实据~~)

看一下官方文档:

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,那么代码的行为如下: 1.如果有返回值,就把返回值保存到局部变量中 2.执行jsr指令跳到finally语句里执行 3.执行完finally语句后,返回之前保存在局部变量表里的值

根据上面的说明就可以轻易地解释为什么是2了。 当执行到return ++x;时,jvm在执行完++x后会在局部变量表里另外分配一个空间来保存当前x的值。 注意,现在还没把值返回给y,而是继续执行finally语句里的语句。等执行完后再把之前保存的值(是2不是x)返回给y。 所以就有了y是2不是3的情况。

其实这里还有一点要注意的是,如果你在finally里也用了return语句,比如return +xx。那么y会是3。因为规范规定了,当try和finally里都有return时,会忽略try的return,而使用finally的return。

本文分享自微信公众号 - 国产程序员(Monday_lida),作者:看似无限透明的你

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-07-20

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • select下拉选中加入c标签

    一觉睡到小时候
  • 快速搭建Spring Boot项目及常用技术整合

    Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而...

    一觉睡到小时候
  • 快速搭建 Git 服务器[Linux版]

    找到server.httpBindInterface,设定服务器的IP地址。这里就设定你的服务器IP。

    一觉睡到小时候
  • 关于 Java finally 执行顺序 -- 修改版

    一份执着✘
  • 你真的了解try{ return }finally{}中的return?

    刚看到这个问题后。突然发现基础不够扎实,居然来第一个都答不出来。。。(不知道还有木有和我也一样也回答不出以上的问题的? 如果有请在评论里告诉我一声,让我知道,我...

    用户1655470
  • Java关键字 Finally执行与break, continue, return等关键字的关系

    长文短总结: 在程序没有在执行到finally之前异常退出的情况下,finally是一定执行的,即在finally之前的return语句将在finally执行...

    老白
  • Java finally语句到底是在return之前还是之后执行?

    网上有很多人探讨Java中异常捕获机制try...catch...finally块中的finally语句是不是一定会被执行?很多人都说不是,当然他们的回答是正...

    bear_fish
  • 【Android】如何知道某个Activity是否在前台?

    Gavin-ZYX
  • UiAutomator源码学习(1)-- UiDevice

    UiDevice提供对设备状态信息的访问。 也可以使用此类来模拟设备上的用户操作,例如按键盘或按Home和Menu按钮。UiDevice类的完整源码 UiDev...

    yuanyuan
  • Python finally的用法

    try语句有一个可选finally子句,用于定义在所有情况下都必须执行的finally操作

    于小勇

扫码关注云+社区

领取腾讯云代金券