有return的情况下try catch finally的执行顺序

  1. 在遇到Exception 并且没有catch的情况下finally语句块没有执行
  2. System.exit(0),终止了 Java 虚拟机的运行, finally语句块没有执行

理解一下finally

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.

它允许程序员避免因返回,继续或中断而意外绕过清理代码。 将清理代码放在finally块中始终是一种很好的做法,即使没有预期的例外情况也是如此。

注意:如果在执行try或catch代码时JVM退出,则finally块可能无法执行。 同样,如果执行try或catch代码的线程被中断或终止,则即使应用程序作为一个整体继续,finally块也可能无法执行。

举例分析

finally 语句块在 try 语句块中的 return 语句之前执行

public class FinallyTest {
public static void main(String[] args) { System.out.println(new FinallyTest().test());
;
}
static int test() {
int x = 1;
try {
System.out.println("try");
return 0;
} finally {
System.out.println("Finally");
}
}
}

执行结果

try
Finally
0

说明 finally 语句块在 try 语句块中的 return 语句之前执行。

finally 语句块在 catch 语句块中的 return 语句之前执行

public class FinallyTest {
public static void main(String[] args) { System.out.println(new FinallyTest().test());
;
}
static int test() {
int x = 1;
try {
System.out.println("try");
x /= 0;
return 0;
} catch (Exception e) {
System.out.println("catch");
return 1;
} finally {
System.out.println("Finally");
return 2;
}
}
}

输出结果

try
catch
Finally
2

看一下trick

code1

static int test() {
try {
return 0;
} finally {
return 1;
}
}

运行结果

1

code2

static int test() {
int i = 1;
try {
return i;
} finally {
i++;
}
}

运行结果

1

实际上,Java 虚拟机会把 finally 语句块作为 subroutine(对于这个 subroutine 不知该如何翻译为好,干脆就不翻译了,免得产生歧义和误解。)直接插入到 try 语句块或者 catch 语句块的控制转移语句之前。但是,还有另外一个不可忽视的因素,那就是在执行 subroutine(也就是 finally 语句块)之前,try 或者 catch 语句块会保留其返回值到本地变量表(Local Variable Table)中。待 subroutine 执行完毕之后,再恢复保留的返回值到操作数栈中,然后通过 return 或者 throw 语句将其返回给该方法的调用者(invoker)。请注意,前文中我们曾经提到过 return、throw 和 break、continue 的区别,对于这条规则(保留返回值),只适用于 return 和 throw 语句,不适用于 break 和 continue 语句,因为它们根本就没有返回值。

经典案例必看

public class FinallyTest {
public static void main(String[] args) {
System.out.println(new FinallyTest().test());
} static String test() {
try {
System.out.println("try");
return test1();
} finally {
System.out.println("finally");
}
}
static String test1() {
System.out.println("test1()");
return "return test";
}
}

执行结果

try
test1()
finally
return test

为什么会这样执行呢?

return test1();
可以拆分成两个
String temp = test1();
return temp;

因此呢会先将try 代码块中的return放到局部变量表里,入栈,接着执行finally代码块的内容,最后return try中的内容

更经典的案例

public class FinallyTest {
public static void main(String[] args) {
System.out.println(new FinallyTest().test());
} static String test() {
try {
System.out.println("try");
return test1();
} finally {
System.out.println("finally");
return "finally end";
}
}
static String test1() {
System.out.println("test1()");
return "return test";
}
}

运行结果

try
test1()
finally
finally end

因此可以分析

总结

先将try 代码块中的return的变量放到局部变量表里,操作数栈入栈,接着执行finally代码块的内容,(如果finally没有return语句的话,最后操作数栈出栈return try中的内容) (如果finally有return语句的话,最后return finally中的内容)

参考资料

关于 Java 中 finally 语句块的深度辨析

try finally 执行顺序问题的更多相关文章

  1. Java的初始化块、静态初始化块、构造函数的执行顺序及用途探究

    Java与C++有一个不同之处在于,Java不但有构造函数,还有一个”初始化块“(Initialization Block)的概念.下面探究一下它的执行顺序与可能的用途. 执行顺序 首先定义A, B, ...

  2. MonoBehaviour Lifecycle(生命周期/脚本执行顺序)

    脚本执行顺序 前言 搭建一个示例来验证Unity脚本的执行顺序,大概测试以下部分: 物理方面(Physics) 渲染(Scene rendering) 输入事件(InputEvent) 流程图 Uni ...

  3. Unity中脚本的执行顺序总结(@WhiteTaken)

    (Editor)以上是Unity官方文档中的截图,脚本在被挂载到物体上,会启用Editor的方法Reset. (Initialization)当执行脚本开始,初始化的过程中,依次执行的是Awake-& ...

  4. 《Java编程思想》学习笔记(二)——类加载及执行顺序

    <Java编程思想>学习笔记(二)--类加载及执行顺序 (这是很久之前写的,保存在印象笔记上,今天写在博客上.) 今天看Java编程思想,看到这样一道代码 //: OrderOfIniti ...

  5. Java学习笔记__异常机制_try_catch_finally_return执行顺序

    package cn.xiaocangtian.Exception; import java.io.FileInputStream; import java.io.FileNotFoundExcept ...

  6. 关于sql的执行顺序

    标准sql的解析顺序为 1)FROM子句,组装来自不同数据源的数据 2)WHERE子句 基于制定的条件对记录进行筛选 3)GROUP BY 子句将数据划分为多个分组 4)使用聚合函数进行计算 5) 使 ...

  7. SQL 语句与性能之执行顺序

    select * , t3.Name from t1 left join t2 on t1.sysno = t2.Asysno left join t3 on t3.sysno = t2.Bsysno ...

  8. 关于JavaScript预编译和执行顺序以及函数引用类型的思考

    昨晚在对项目中的一部分做模块化处理的时候,遇到了一个问题,一个重新定义的function对一个通用类中的function进行赋值覆盖的时候,失败了.问题抽象出来是这样的: <script > ...

  9. JMeter专题系列(三)元件的作用域与执行顺序

    1.元件的作用域 JMeter中共有8类可被执行的元件(测试计划与线程组不属于元件),这些元件中,取样器是典型的不与其它元件发生交互作用的元件,逻辑控制器只对其子节点的取样器有效,而其它元件(conf ...

  10. [转载]T-SQL(Oracle)语句查询执行顺序

    原文链接:http://blog.sina.com.cn/s/blog_61c006ea0100mlgq.html sql语法的分析是从右到左,where子句中的条件书写顺序,基本上对sql性能没有影 ...

随机推荐

  1. 说说html 的<!DOCTYPE>声明&标准模式与兼容模式

    我们都知道<!DOCTYPE>声明位于文档的最前面,处于<html>标签之前. <!DOCTYPE>声明不是html标签,它的作用:告知web浏览界面应该使用哪个h ...

  2. 如何在Sitecore CMS中创建没有标准字段的模板

    当创建一个模板,Sitecore的将默认为扩大“标准模板”,它位于/sitecore/templates/System/Templates. 如果您选择不扩展任何模板或从“基本模板”字段中删除标准模板 ...

  3. Maven的配置指南

    Maven的配置指南  配置Maven Maven配置发生在3个级别: 项目 - 大多数静态配置发生在pom.xml中 安装 - 这是Maven安装时发生的一次性的配置过程 用户 - 这是Maven提 ...

  4. python读取excel中单元格的内容返回的5种类型

    (1) 读取单个sheetname的内容. 此部分转自:https://www.cnblogs.com/xxiong1031/p/7069006.html python读取excel中单元格的内容返回 ...

  5. 概念、DW介绍

    网页设计知识点大致分为五个部分,分别是: 1.概念.DW介绍: 2.标签: 3.样式表CSS: 4.JQuery: 5.JavaScript 概念.DW介绍: 一.网页的基本结构 <!--文档声 ...

  6. MySql语句分类

    SQL语言分为四大类:数据定义语言DDL,数据查询语言DQL,数据操作语言DML,数据控制语言DCL [1]数据定义语言DDL 数据定义语言DDL,用于创建.修改.删除数据库内的数据结构.如下: (1 ...

  7. mitmproxy 中间人攻击的小玩笑

    import mitmproxy.http from mitmproxy import ctx, http class Joker: def request(self, flow: mitmproxy ...

  8. Web 应用架构基础课(转载)

    Web 应用架构基础课 初级 web 应用开发者必学的基础网络架构概念 web 应用主流架构概览 上图便是我司(Storyblocks)网络架构的很好展现.如果你还没成为经验老道的 web 工程师,可 ...

  9. いろはちゃんとマス目 / Iroha and a Grid (组合数学)

    题目链接:http://abc042.contest.atcoder.jp/tasks/arc058_b Time limit : 2sec / Memory limit : 256MB Score ...

  10. [转载]C#中IndexOf的使用

    注:此方法无法找出目标字符串第二次.第三次等出现的位置. 具体代码如下所示: 1 2 3 4 5 var array=['REG','2018','2018'];   array.indexOf(‘R ...