有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. html5-增强的表单

    <!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8&qu ...

  2. Sql日期时间格式转换[zhuan]

    sql server2000中使用convert来取得datetime数据类型样式(全) 日期数据格式的处理,两个示例: CONVERT(varchar(16), 时间一, 20) 结果:2007-0 ...

  3. Spring tokenizeToStringArray

    tokenizeToStringArray: StringUtils.tokenizeToStringArray(pattern, this.pathSeparator, this.trimToken ...

  4. Spring NoSuchBeanDefinitionException

    转http://www.baeldung.com/spring-nosuchbeandefinitionexception 1. Overview In this article, we are di ...

  5. c# 规范用户输入控件

    MaskedTextBox控件是一种特殊的文本框,它可以通过Mask属性设置格式标记符.在应用程序运行后,用户只能输入Mask属性允许的内容,列入日期.电话等 在“输入掩码”对话框的右下角有一个“使用 ...

  6. SQL 语法速记

    ----------------------------------DML(数据操作语言)---------------------------------- -- 一.INSERT VALUES语句 ...

  7. Promise的简单用法

    众所周知的,Javascript是一种单线程的语言,所有的代码必须按照所谓的“自上而下”的顺序来执行.本特性带来的问题就是,一些将来的.未知的操作,必须异步实现.本文将讨论一个比较常见的异步解决方案— ...

  8. Linux系统管理和维护常用命令

    Linux系统管理和维护常用命令 ls 命令 功能说明 ls 命令显示指定工作目录下的内容,列出工作目录所包含的文件及子目录. 语法结构: ls [选项] [路径或文件] ls 选项及说明 -a 显示 ...

  9. <转>jmeter(六)元件的作用域与执行顺序

    本博客转载自:http://www.cnblogs.com/imyalost/category/846346.html 个人感觉不错,对jmeter讲解非常详细,担心以后找不到了,所以转发出来,留着慢 ...

  10. 怎样从外网访问内网IIS?

    本地安装了一个IIS,只能在局域网内访问,怎样从外网也能访问到本地的IIS呢?本文将介绍具体的实现步骤. 准备工作 安装并启动IIS 默认安装的IIS端口是80. 实现步骤 下载并解压holer软件包 ...