关于 Java finally 执行顺序 -- 修改版

前言

之前写了一篇 关于 try-catch-finally 执行顺序 的文章,但是写的有些繁琐了,这里重新写一下。

题目

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);
    }
}

我第一次看到这个题,得出了几个问题:

  • 如果在 try 语句块里有 return 语句,那么 finally 还会执行吗?
  • 如果执行那应该是怎样的执行过程呢?

首先这道题的运行结果是 2,可能跟你想的不一样吧,别急,下面我会慢慢解释的。

在学习 Java 基础的时候,老师就讲过,try-catch-finally 中的 finally 语句块一定会被执行,那么我们来 debug 一下:

初始状态:

此时运行到了 return ++x; 但还没执行该语句,目前 x 的值为 1.

这时发现跳到了 finally 语句块中,且 return ++x++ 操作已经执行,但没有进行 reutrn,目前 x 的值为 2:

执行完 finally 语句块中的 ++x 操作后,又回到了 return 中,此时 x 的值为 3:

但根据最后的运行结果,我们发现其实真正 reutrn 的是 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,那么代码的行为如下:

  1. 如果有返回值,就把返回值保存到局部变量中
  2. 执行 jsr 指令跳到 finally 语句里执行
  3. 执行完 finally 语句后,返回之前保存在局部变量表里的值

看完这个应该就能理解为什么返回的是 2 了,

但要注意的是:

  • 如果在 finally 语句块中也使用了 return 语句,那么会忽略 try 中的 return 语句,而执行 finally 中的 return。
  • 如果 try 中 return 的是引用数据类型,那么 finally 中的操作可能会影响最终的 return 值,因为对于引用数据类型,暂存到局部变量里的是它的地址值。

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

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏CDA数据分析师

工具 | 学习总结:当我学完Python我学了些什么

本文是本人学完Python后的一遍回顾,加深理解顺便留作手册以备查阅。 学习Python的这几天来,觉得Python还是比较简单,容易上手的,就基本语法而言,...

229100
来自专栏coding for love

JS入门难点解析8-作用域,作用域链,执行上下文,执行上下文栈等分析

(注1:如果有问题欢迎留言探讨,一起学习!转载请注明出处,喜欢可以点个赞哦!) (注2:更多内容请查看我的目录。)

13010
来自专栏Java帮帮-微信公众号-技术文章全总结

【大牛经验】探讨Java的异常与错误处理

探讨Java的异常与错误处理 ENTER TITLE ? Java中的异常处理机制已经比较成熟,我们的Java程序到处充满了异常的可能,如果对这些异常不做预先的...

39160
来自专栏向治洪

Android热补丁技术—dexposed原理简析(手机淘宝采用方案)

上篇文章《Android无线开发的几种常用技术》我们介绍了几种android移动应用开发中的常用技术,其中的热补丁正在被越来越多的开发团队所使用,它涉及到da...

30760
来自专栏从零开始学 Web 前端

C/C++练习题(二)

2、查找字符串中第一个只出现一次的字符并输出。(如:aabbcddefg 则输出 'c')

13640
来自专栏SDNLAB

Open vSwitch系列之数据结构解析深入分析Hmap

作为Open vSwitch系列的第一篇文章,选择分析哪个数据结构我思考很久,最后还是选择比较常见而且很基础的结构hmap。 在Open vSwitch世界中很...

39140
来自专栏java学习

看看你对队列的了解有多少?

1.1队列概念及基本操作 队列(Queue) 简称队,它同堆栈一样,也是一种运算受限的线性表,其限制是仅允许在表的一端进行插入,而在表的另一端进行删除。在队列中...

37850
来自专栏Java面试通关手册

可能是把Java内存区域讲的最清楚的一篇文章

哈哈 皮一下!我自己开源的一个Java学习指南文档。一份涵盖大部分Java程序员所需要掌握的核心知识,正在一步一步慢慢完善,期待您的参与。Github地址:ht...

11920
来自专栏自学笔记

python基本常识

tuple,str都可以看做是一种list,都可以进行切片操作。 利用切片操作,去掉一个字符串的前后空格。要注意是是前后空格是不止一个的,可能有很多个。

43750
来自专栏Crossin的编程教室

【Python 第24课】 if的嵌套

和for循环一样,if也可以嵌套使用,即在一个if/elif/else的内部,再使用if。这有点类似于电路的串联。 if 条件1: if 条件2: ...

32360

扫码关注云+社区

领取腾讯云代金券