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性能没有影 ...
随机推荐
- 六 js函数和this
js的所有代码都是由funtion组成,funtion即函数的类型. 一.函数有两种写法 -----1.定义式 function test() { //定义一个函数 console.log(" ...
- Python之words count
要求: 对文件单词进行统计,不区分大小写,并显示单词重复最多的十个单词 思路: 利用字典key,value的特性存单词及其重复的次数 每行进行特殊字符的处理,分离出被特殊字符包含的单词 def mak ...
- STL之Map和multimap容器
1.Map和multimap容器 1)map是标准的关联式容器,一个map是一个键值对序列,即(key,value)对.它提供基于key的快速检索能力. 2)map中key值是唯一的.集合中的元素按一 ...
- rest-framework 序列化格式Restful API设计规范
理解RESTful架构 Restful API设计指南 理解RESTful架构 越来越多的人开始意识到,网站即软件,而且是一种新型的软件. 这种"互联网软件"采用客户端/服务器模式 ...
- Tornado安装
Tornado 和现在的主流 Web 服务器框架(包括大多数 Python 的框架)有着明显的区别:它是非阻塞式服务器,而且速度相当快.得利于其 非阻塞的方式和对 epoll 的运用,Tornado ...
- MQTT安装
技术链接:http://docs.emqtt.cn/zh_CN/latest/getstarted.htmlDashboard控制台:http://10.74.20.43:18083/#/ 默认登录用 ...
- [openjudge-动态规划]摘花生
题目描述 描述 Hello Kitty 想摘点花生送给她喜欢的米老鼠.她来到一片有网格状道路的矩形花生地(如下图),从西北角进去,东南角出来.地里每个道路的交叉点上都有种着一株花生苗,上面有若干颗花生 ...
- noip200605能量项链
题解: 状态转移方程为:dp[i][j] = max{dp[i][k] + dp[k+1][j] + a[i]*a[k+1]*a[j+1]}, k=i, ..., j-1, i和j都从1开始.dp[i ...
- oracle 游标/函数/存储过程/触发器 表空间
--存储过程,循环create or replace procedure delTables(ename t_emp.ename%TYPE)AScon number;i NUMBER := 1;tab ...
- GUI常用对象介绍2
%示意line对象的用法 hf=figure; hl=plot([:]); %示意line对象的属性 get(hl) %设置line的颜色 set(hl,'Color','r'); %设置每个点形状 ...