try finally 执行顺序问题
有return的情况下try catch finally的执行顺序
- 在遇到Exception 并且没有catch的情况下
finally
语句块没有执行 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中的内容)
参考资料
try finally 执行顺序问题的更多相关文章
- Java的初始化块、静态初始化块、构造函数的执行顺序及用途探究
Java与C++有一个不同之处在于,Java不但有构造函数,还有一个”初始化块“(Initialization Block)的概念.下面探究一下它的执行顺序与可能的用途. 执行顺序 首先定义A, B, ...
- MonoBehaviour Lifecycle(生命周期/脚本执行顺序)
脚本执行顺序 前言 搭建一个示例来验证Unity脚本的执行顺序,大概测试以下部分: 物理方面(Physics) 渲染(Scene rendering) 输入事件(InputEvent) 流程图 Uni ...
- Unity中脚本的执行顺序总结(@WhiteTaken)
(Editor)以上是Unity官方文档中的截图,脚本在被挂载到物体上,会启用Editor的方法Reset. (Initialization)当执行脚本开始,初始化的过程中,依次执行的是Awake-& ...
- 《Java编程思想》学习笔记(二)——类加载及执行顺序
<Java编程思想>学习笔记(二)--类加载及执行顺序 (这是很久之前写的,保存在印象笔记上,今天写在博客上.) 今天看Java编程思想,看到这样一道代码 //: OrderOfIniti ...
- Java学习笔记__异常机制_try_catch_finally_return执行顺序
package cn.xiaocangtian.Exception; import java.io.FileInputStream; import java.io.FileNotFoundExcept ...
- 关于sql的执行顺序
标准sql的解析顺序为 1)FROM子句,组装来自不同数据源的数据 2)WHERE子句 基于制定的条件对记录进行筛选 3)GROUP BY 子句将数据划分为多个分组 4)使用聚合函数进行计算 5) 使 ...
- SQL 语句与性能之执行顺序
select * , t3.Name from t1 left join t2 on t1.sysno = t2.Asysno left join t3 on t3.sysno = t2.Bsysno ...
- 关于JavaScript预编译和执行顺序以及函数引用类型的思考
昨晚在对项目中的一部分做模块化处理的时候,遇到了一个问题,一个重新定义的function对一个通用类中的function进行赋值覆盖的时候,失败了.问题抽象出来是这样的: <script > ...
- JMeter专题系列(三)元件的作用域与执行顺序
1.元件的作用域 JMeter中共有8类可被执行的元件(测试计划与线程组不属于元件),这些元件中,取样器是典型的不与其它元件发生交互作用的元件,逻辑控制器只对其子节点的取样器有效,而其它元件(conf ...
- [转载]T-SQL(Oracle)语句查询执行顺序
原文链接:http://blog.sina.com.cn/s/blog_61c006ea0100mlgq.html sql语法的分析是从右到左,where子句中的条件书写顺序,基本上对sql性能没有影 ...
随机推荐
- Yii2 Gridview查询关联筛选
- html5-常用的通用元素
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8&qu ...
- NSOperation、NSOperationQueue(III)
NSOperation.NSOperationQueue 常用属性和方法归纳 NSOperation 常用属性和方法 a. 取消操作方法 //可取消操作,实质是标记 isCancelled 状态. - ...
- 利用QPainter绘制散点图
[1]实例代码 (1)代码目录结构(备注:QtCreator默认步骤新建工程) (2)工程pro文件 QT += core gui greaterThan(QT_MAJOR_VERSION, ): Q ...
- react+redux+react-router+node.js 开发实时聊天App 学习记录
一.课程导学 1.React 主要解决的是UI层的问题,应用的状态需要借助Redux等状态管理. 2.前端React + antd-mobile UI组件库 + Redux 状态管理库 + Rea ...
- HDU 2064 汉诺塔III (递推)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2064 约19世纪末,在欧州的商店中出售一种智力玩具,在一块铜板上有三根杆,最左边的杆上自上而下.由小到 ...
- <转>jmeter(二)录制脚本
本博客转载自:http://www.cnblogs.com/imyalost/category/846346.html 个人感觉不错,对jmeter讲解非常详细,担心以后找不到了,所以转发出来,留着慢 ...
- Java常用API、Math类介绍
一.API的概述 API——Application Programing Interface:应用程序编程接口,是java提供的一些预定义的函数: 目的:基于API实现程序的快速编写,只需了解其作用, ...
- ogg 12.3 for sqlserver 2016 CDC模式配置
本文主要讲述ogg 12.3 通过CDC抽取sqlserver 2016 enterprise的过程,投递配置相对简单,所以不在此阐述. 配置步骤概述 1. 解压ogg 12.3 for sqlser ...
- qt中QtreeWidget与QstackWidget关联的问题
过程:要做一个图书管理系统,主界面是类似于这样的 左边是类似于树形空间的东西,当点击左边的左边的窗体的时候,右边的窗口也会跟着切换. 为了实现这个功能,必须要有两个控件,QTreeWidget和Qst ...