Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >try catch finally 执行顺序详解

try catch finally 执行顺序详解

作者头像
肉眼品世界
发布于 2021-08-09 08:04:38
发布于 2021-08-09 08:04:38
60100
代码可运行
举报
文章被收录于专栏:肉眼品世界肉眼品世界
运行总次数:0
代码可运行

链接:https://blog.csdn.net/u013309870/article/details/73498860

引言

关于try catch finally 执行顺序的笔试面试题目非常的多,我曾经在牛客网刷题的时候不止一次的碰到过,而且不止一次的做错过,这里面需要涉及的细节如果不弄清楚每次做题就会产生似是而非的感觉。这次查阅了很多相关资料,关于try catch finally 执行顺序各方面基本都讲到了。不足之处欢迎指出。

try catch finally 执行顺序

仅仅在下面4中情况下不会执行finally语句 :

①.如果在try 或catch语句中执行了System.exit(0)。

②.在执行finally之前jvm崩溃了。

③.try语句中执行死循环。

④.电源断电。

除了以上的四种情况外,finally语句都会执行,finally语句执行时会有以下原则。

①、不管有没有出现异常,finally块中代码都会执行;

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  public void demo1(){
        try {

          System.out.println(result);

        } catch (Exception e) {                     
            System.out.println(e.getMessage());
        }
         finally {            
                System.out.println("finally trumps. ");
            }

//输出结果为:
result
finally trumps .

上面代码可知如果未出现异常是顺序执行try和finally代码块。

②、当try和catch中有return时,finally仍然会执行;

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public static int demo2() {
        try {
            return 0;
        }
        finally {
            System.out.println("finally trumps return.");
        }
    }
//输出结果

finally trumps return.
0   

当finally里面没有return语句是,执行try 和finally语句之后最后再执行return。 ③、finally是在return后面的表达式运算后执行的(此时并没有返回运算后的值,而是先把要返回的值保存起来,管finally中的代码怎么样,返回的值都不会改变,任然是之前保存的值),所以函数返回值是在finally执行前确定的;

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public static int demo3()
    {
         int i = 0;
            try {
                i = 2;
                return i;
            } finally {
                i = 12;
                System.out.println("finally trumps return.");
            }       
    }
//输出结果
    finally trumps return.
    2

此处中finally中对i赋值12但是demo3的返回值仍然是2,也就是在finally中对i赋值并未改变i的返回值,这里需要详细的讲一下,此处涉及到了jvm机制。先给出上面代码的字节码然后给出图解:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public static demo3()I
    TRYCATCHBLOCK L0 L1 L2 
   L3
    LINENUMBER 12 L3
    ICONST_0
    ISTORE 0
   L0
    LINENUMBER 14 L0
    ICONST_2
    ISTORE 0
   L4
    LINENUMBER 15 L4
    ILOAD 0
    ISTORE 2
   L1
    LINENUMBER 17 L1
    BIPUSH 12
    ISTORE 0
   L5
    LINENUMBER 18 L5
    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
    LDC "finally trumps return."
    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
   L6
    LINENUMBER 15 L6
    ILOAD 2
    IRETURN
   L2
    LINENUMBER 16 L2
   FRAME FULL [I] [java/lang/Throwable]
    ASTORE 1
   L7
    LINENUMBER 17 L7
    BIPUSH 12
    ISTORE 0
   L8
    LINENUMBER 18 L8
    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
    LDC "finally trumps return."
    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
   L9
    LINENUMBER 19 L9
    ALOAD 1
    ATHROW

上面的字节码比较长,下面简要的讲一下,其实我在http://blog.csdn.net/u013309870/article/details/72935274这篇文章中详细的讲过方法中代码的执行过程,

在variable内存中有两个变量区域一个是用来存放i的值,对应最上面的那个,另一个用于存放返回值。在上面代码执行到i = 2; return i;先对i赋值2,然后执行return语句此时并不是将结果返回,而是将i=2的值保存到返回值变量区域,在执行完i=12时,再返回variable中返回值地址变量区域的2。

④、finally中最好不要包含return,否则程序会提前退出,返回值不是try或catch中保存的返回值。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    public static int demo4() {
        int i = 0;
        try {
            return i;
        } finally {
            i = 12;
            System.out.println("finally trumps return.");
            return i;
        }
    }
    //输出结果
    finally trumps return.
    12  

上面为什么会返回12呢?因为在程序还未执行try中的return语句时就先执行了finally里面的return语句所以返回结果为12。

经典面试题 下面题目输出什么?

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    public static int demo5() {
        try {
            return printX();
        }
        finally {
            System.out.println("finally trumps return... sort of");
        }
    }
    public static int printX() {

        System.out.println("X");
        return 0;
    }

输出结果:

X
finally trumps return... sort of
0
1
2
3

上面这道题目含金量很高,程序顺序执行时先执行printX()函数,此时得到返回值0并且将0保存到variable中对应的用于保存返回值的区域,此时程序在执行finally语句因为finally语句中没有return语句,所以程序将返回值区域的0返回给上一级函数。

参考文献 https://stackoverflow.com/questions/65035/does-finally-always-execute-in-java http://blog.csdn.net/u013309870/article/details/72935274 深入理解Java虚拟机(高清第二版)JVM高级特性与最佳实践

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-08-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 肉眼品世界 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Java关键字 Finally执行与break, continue, return等关键字的关系
长文短总结: 在程序没有在执行到finally之前异常退出的情况下,finally是一定执行的,即在finally之前的return语句将在finally执行之后执行。 finally总是在控制转移语句(break,continue,return等)执行之前执行。 可不能小看这个简单的 finally,看似简单的问题背后,却隐藏了无数的玄机。接下来我就带您一步一步的揭开这个 finally 的神秘面纱。 问题分析 首先来问大家一个问题:finally 语句块一定会执行吗? 很多人都认为 finally
老白
2018/03/19
3.8K0
Java关键字 Finally执行与break, continue, return等关键字的关系
有return的情况下try catch finally的执行顺序(最有说服力的总结)
结论: 1、不管有木有出现异常,finally块中代码都会执行; 2、当try和catch中有return时,finally仍然会执行; 3、finally是在return后面的表达式运算后执行的(此时并没有返回运算后的值,而是先把要返回的值保存起来,管finally中的代码怎么样,返回的值都不会改变,任然是之前保存的值),所以函数返回值是在finally执行前确定的; 4、finally中最好不要包含return,否则程序会提前退出,返回值不是try或catch中保存的返回值。 举例: 情况1:try{} catch(){}finally{} return; 显然程序按顺序执行。 情况2:try{ return; }catch(){} finally{} return; 程序执行try块中return之前(包括return语句中的表达式运算)代码; 再执行finally块,最后执行try中return; finally块之后的语句return,因为程序在try中已经return所以不再执行。 情况3:try{ } catch(){return;} finally{} return; 程序先执行try,如果遇到异常执行catch块, 有异常:则执行catch中return之前(包括return语句中的表达式运算)代码,再执行finally语句中全部代码, 最后执行catch块中return. finally之后也就是4处的代码不再执行。 无异常:执行完try再finally再return. 情况4:try{ return; }catch(){} finally{return;} 程序执行try块中return之前(包括return语句中的表达式运算)代码; 再执行finally块,因为finally块中有return所以提前退出。 情况5:try{} catch(){return;}finally{return;} 程序执行catch块中return之前(包括return语句中的表达式运算)代码; 再执行finally块,因为finally块中有return所以提前退出。 情况6:try{ return;}catch(){return;} finally{return;} 程序执行try块中return之前(包括return语句中的表达式运算)代码; 有异常:执行catch块中return之前(包括return语句中的表达式运算)代码; 则再执行finally块,因为finally块中有return所以提前退出。 无异常:则再执行finally块,因为finally块中有return所以提前退出。
全栈程序员站长
2022/07/04
2870
jvm之类文件详解(四)
Class 文件是一组以 8 位字节为基础单位的二进制流,各个数据项目严格按照顺序紧凑地排列在 Class 文件之中,中间没有添加任何 分隔符,这使得整个 Class 文件中存储的内容几乎全部是程序运行的必要数据,没有空隙存在。 当遇到需要占用 8 位字节以上空间的数据项时,则会按照高位在前(Big-Endian)的方式分割成若干个 8 位字节进行存储。 Class 文件只有两种数据类型:无符号数和表 链接:https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html
周杰伦本人
2022/10/25
2010
jvm之类文件详解(四)
java finally深入探究
When---什么时候需要finally: 在jdk1.7之前,所有涉及到I/O的相关操作,我们都会用到finally,以保证流在最后的正常关闭。jdk1.7之后,虽然所有实现Closable接口的流,可以通过在try块中定义,从而实现jvm自动关闭输入输出流。但其实在我们需要在代码块返回之前,实现在不管前面的操作是否执行成功,都要执行的某操作A。这时候我们就可以将A放入finally块中。很常见的一个操作就是锁的unlock操作。 What---什么是finally: 字面解释就是最终,eventuall
SecondWorld
2018/03/14
7220
Java中关于try、catch、finally中的细节分析
本文讲解的是关于Java中关于try、catch、finally中一些问题 下面看一个例子(例1),来讲解java里面中try、catch、finally的处理流程 public class TryCatchFinally { @SuppressWarnings("finally") public static final String test() { String t = ""; try { t = "try"; r
三哥
2018/06/15
1.7K3
【Java学习笔记之三十三】详解Java中try,catch,finally的用法及分析
这一篇我们将会介绍java中try,catch,finally的用法 以下先给出try,catch用法: try {   //需要被检测的异常代码 } catch(Exception e) { //异常处理,即处理异常代码 } finally {   //一定会被执行的代码 } 代码区如果有错误,就会返回所写异常的处理。 首先要清楚,如果没有try的话,出现异常会导致程序崩溃。而try则可以保证程序的正常运行下去,比如说: try { int i = 1/0; } catch(Exc
Angel_Kitty
2018/04/09
8.5K0
Kotlin 类扩展实现原理
在 Kotlin 中当项目集成第三方 SDK 的时候,如果需要为其中某个类新增方法来可以通过 className.methodName(){}, 即 类名.方法名 的形式来扩展函数,那么同样和 Java 一样是 JVM 语言的 Kt 为什么就可以实现这种功能呢,以下为一个例子,借助它来详细探讨一下实现原理及细节。
萬物並作吾以觀復
2021/07/20
4150
写给小白看的入门级 Java 基本语法
从表面上看,这句话有点讽刺我的文章写得不够通俗易懂的意味,但我心胸一直如大海一般开阔,你了解的。所以,我回他,“你还不如把培训费给我,哈哈。”怎么样,你也能体会到我的幽默,以及无情吧?当然了,是时候写一篇文章(也许是一个系列哦)照顾一下顾小白群体的情绪了,帮他们入入门或者回炉再造下。
沉默王二
2020/04/21
3250
写给小白看的入门级 Java 基本语法
由一道 Java finally 执行顺序的题引发的思考
前言 本文讲解过于繁琐,已重新修改至 关于 Java finally 执行顺序 -- 修改版。 原题 首先来看看这道题: public class test1 { static String s = "A"; public static void main(String[] args) { System.out.println(test()); System.out.println(s); } private static String
一份执着✘
2018/06/04
5630
Java class类文件和类加载器详解以及代码优化
JVM就是Java虚拟机,它是Java程序运行的载体。 计算机只识别0和1。Java是⾼级语⾔。⾼级语⾔编写的程序要想被计算机执⾏,需要变成⼆进制形式的本地机器码。能直接变成机器码的语义是C++,它的缺点是不同操作系统,需要准备多份。Java需要先变成Java字节码(class⽂件)。然后再变成机器码。JVM可以实现Java的⼀次编译,到处运⾏。 这个就是区别于类似于C语⾔的⽅式。机器码是电脑CPU直接读取运行的机器指令,运行速度最快,但是非常晦涩难懂,也比较难编写,一般从业人员接触不到。字节码是一种中间状态(中间码)的二进制代码(文件)。需要直译器转译后才能成为机器码。
共饮一杯无
2022/11/24
1.1K0
Java class类文件和类加载器详解以及代码优化
JUC学习笔记——共享模型之不可变
但是我们可以选择更换一种日期类型,我们选择不可改变的日期类就可以完成并发下的数据修改问题:
秋落雨微凉
2022/11/21
3170
你真的理解 Java 中的 try_catch_finally 吗?
try…catch…finally恐怕是大家再熟悉不过的语句了,而且感觉用起来也是很简单,逻辑上似乎也是很容易理解。不过,我亲自体验的“教训”告诉我,这个东西可不是想象中的那么简单、听话。不信?
淡定的蜗牛
2019/09/19
6670
你真的理解 Java 中的 try_catch_finally 吗?
001. JAVA程序运行原理分析
1. 先来看看JVM运行时数据区的结构 线程独占: 每个线程都有它独立的空间,随线程生命周期而创建和销毁。 线程共享: 所有线程能访问这块内存数据,随虚拟机GC 而创建和销毁。 方法区 JVM 用来存
山海散人
2021/03/03
3950
001. JAVA程序运行原理分析
从JVM层面来解释i++和++i的真正区别
但是这简单的回答并不能入吸引面试官的眼球,如果用java字节码指令分析则效果完全不同。
肉眼品世界
2021/07/13
4050
从JVM层面来解释i++和++i的真正区别
你真的了解 try catch finally 吗?
原文链接 https://juejin.cn/post/7291931828029358118
GeeJoe
2023/10/24
3890
你真的了解 try catch finally 吗?
try-catch-finally中的4个大坑,不小心就栽进去了!
在 Java 语言中 try-catch-finally 看似简单,一副人畜无害的样子,但想要真正的“掌控”它,却并不是一件容易的事。别的不说,咱就拿 fianlly 来说吧,别看它的功能单一,但使用起来却“暗藏杀机”,若您不信,咱来看下面的这几个例子...
磊哥
2021/02/02
9860
【Java ——异常机制详解】
异常指不期而至的各种状况,如:文件找不到、网络连接失败、非法参数等。异常是一个事件,它发生在程序运行期间,干扰了正常的指令流程。Java通 过API中Throwable类的众多子类描述各种不同的异常。因而,Java异常都是对象,是Throwable子类的实例,描述了出现在一段编码中的 错误条件。当条件生成时,错误将引发异常。
奥耶可乐冰
2024/05/31
2550
​Java中关于try、catch、finally中的细节分析
阿里巴巴开发手册中有这么一条:【强制】不要在 finally 块中使用 return , 在开发过程中发现部分同学对这条规则理解不是很透彻,本文将就 try 、catch、finally 的一些问题,分析一下 try 、catch、finally 的处理流程。
weylan
2021/10/29
1.1K0
JVM学习笔记——类加载和字节码技术篇
在本系列内容中我们会对JVM做一个系统的学习,本片将会介绍JVM的类加载和字节码技术部分
秋落雨微凉
2022/11/16
5590
JVM学习笔记——类加载和字节码技术篇
【Java疑难杂症】有return的情况下try catch finally的执行顺序
文章介绍了异常处理的原理,总结了解决办法,分析了在实际编程中可能遇到的问题以及解决方法,包括使用try-catch语句和自定义异常。
弗兰克的猫
2018/01/09
6690
推荐阅读
相关推荐
Java关键字 Finally执行与break, continue, return等关键字的关系
更多 >
领券
社区富文本编辑器全新改版!诚邀体验~
全新交互,全新视觉,新增快捷键、悬浮工具栏、高亮块等功能并同时优化现有功能,全面提升创作效率和体验
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文