finally语句块是搭配着try语句块出现的,也就说必须有try语句块才会有finally语句块,但是并不是try语句块都会搭配有finally语句块出现,我们常见的更多是try...catch...

finally语句块一般出现的情况如下:

public int operation() {
int result = 2016;
/*statements*/
try {
/*statements*/
} catch (Exception e) {
/*statements*/
} finally {
/*statements*/
}
}

一、finally语句块的执行时机

  • finally语句并不是每次都执行,只有线程执行过try语句块,finally语句块才会执行。如果线程执行到try语句块之前就return的话,finally语句是不会执行的。如例程中第一种情况,在try语句块之前执行return语句将会直接退出函数。
  • 只要线程进入过try语句块,不论有没有抛出异常,finally语句块都会执行。如例程中的第二种和第三种情况,线程执行进入try语句块,不管有没有出现异常,finally语句都正常执行。
  • finally 语句块是在结果返回之前执行的。根据第二种和第三种情况,可以发现finally语句执行在main函数打印结果之前。
public class Test {

    public static void main(String[] args) {
System.out.println("return before try");
System.out.println("value: " + test(1));
System.out.println("return after try");
System.out.println("value: " + test(0));
System.out.println("return after try catch");
System.out.println("value: " + test());
} public static int test(int i) {
if (i == 1)
return 0;
try {
System.out.println("try block");
return i;
} finally {
System.out.println("finally block");
}
} public static int test(){
int i = 1;
try {
System.out.println("try block");
i = 1 / 0;
return 1;
}catch (Exception e){
System.out.println("exception block");
return 2;
}finally {
System.out.println("finally block");
}
}
}

执行结果

return before try
value: 0
return after try
try block
finally block
value: 0
return after try catch
try block
exception block
finally block
value: 2

二、finally语句块对返回结果的影响
上面的例子为了不影响读者理解,在finally语句中没有做任何可能会影响到返回结果的操作。但是在finally语句块中对返回结果进行操作的话,会不会对返回结果造成影响就要分情况而论了。在学习接下来这部分知识之前,笔者是坚持认为finally语句对返回结果进行操作,是肯定会影响返回结果的值的,毕竟根据上面的理解,finally语句块执行在结果返回之前嘛,随着深入学习,笔者发现这里面还是有需要注意的地方的。先看一段例程:

public class Test {
public static void main(String[] args) {
System.out.println("value : " + getValue());
} public static int getValue() {
int i = 1;
try {
return i;
} finally {
i++;
}
}
}

执行结果:

value : 1

按照之前的理解,这个程序执行得有点不按套路出牌啊,执行完try语句之后,程序先不返回,接着执行finally语句块,做自增操作,返回值应该是2啊,怎么会是1呢?我不知道各位读者这会什么心情,反正当时我看到这结果的时候,用一脸懵逼来形容是毫不为过。

结果查阅资料,发现这个地方Java里面是有特殊处理的,下面这段话是抄的:
“Java 虚拟机会把 finally 语句块作为 subroutine直接插入到 try 语句块或者 catch 语句块的控制转移语句之前。但是,还有另外一个不可忽视的因素,那就是在执行 subroutine之前,try 或者 catch 语句块会保留其返回值到本地变量表中。待 subroutine 执行完毕之后,再恢复保留的返回值到操作数栈中,然后通过 return 或者 throw 语句将其返回给该方法的调用者。”

也就是说在try...catch...中执行到return语句的时候,会先把需要返回的数据缓存下来,再去执行finally语句块,执行完finally语句块之后,再将缓存的数据作为结果返回。这样看来上面例程的执行结果就说得过去了。是不是好开心,感觉一下子豁然开朗了呢。不要着急,咱们再入一个例程:

public class Test {

    static class Monitor {
int flag; public Monitor(int flag) {
this.flag = flag;
} public void setFlag(int flag) {
this.flag = flag;
} public int getFlag() {
return this.flag;
}
} public static void main(String[] args) {
Monitor monitor = getValue();
System.out.println("flag : " + monitor.getFlag());
} public static Monitor getValue() {
Monitor monitor = new Monitor(0);
try {
return monitor;
} finally {
monitor.setFlag(1);
}
}
}

执行结果:

flag : 1

不是说在执行finally语句之前会把结果缓存的吗?为什么返回的结果会是1,应该是0才对的啊。其实这个地方出现疑问是因为不了解缓存到底存的是什么。这两个例程在我们的理解上产生冲突,是因为这两个例程中,finally语句块操作的是两种类型的变量,一个是基本类型,一个是对象类型。这两种类型的变量的存储方式是不一样的。int等基本类型的变量,在变量对应的内存中直接存放的就是该变量的值,而对象类型的变量,在其对应的内存中存放的是对象所在的地址。执行finally语句之前,Java确实对二者都进行了缓存,缓存的是变量对应的内存中存放的数据,于基本类型而言,缓存的是值,于对象类型而言,缓存的是对象所在内存区块的地址。我们在finally语句中进行操作时,不会影响缓存中存放的数据,这样无论我们对基本类型的值如何操作,返回值始终是之前的值,但是对象类型是不一样的,缓存的数据不变只能保证缓存数据地址指向的一直是同一个对象,finally语句块中对这个对象进行操作,是完全可以影响到对象的属性的。

看到这,暂时算是豁然开朗了,也不知道有没有没挖出来的坑,如果有的话,还请各位大牛不吝赐教。

finally语句块的更多相关文章

  1. .NET基础 一步步 一幕幕[循环、逻辑语句块]

    循环.逻辑语句块   好久不写博客了,断更了好几天了,从上周五到今天,从北京到上海,跨越了1213.0公里,从一个熟悉的城市到陌生的城市,还好本人适应力比较好,还有感谢小伙伴的接风咯,一切都不是事,好 ...

  2. static{ }语句块详解

    static{}(即static块),会在类被加载的时候执行且仅会被执行一次,一般用来初始化静态变量和调用静态方法.举ge例子: public class Test { public static i ...

  3. begin-end语句块在mysql中的使用问题

    在最近在通过navicate连接mysql数据库时,进行查询操作: delimiter $$BEGIN SET @a=1; if (@a > 0) THEN SELECT COUNT(*) fr ...

  4. 转 java中static{}语句块详解

    原文地址:http://blog.csdn.net/lubiaopan/article/details/4802430     感谢原作者! static{}(即static块),会在类被加载的时候执 ...

  5. java中static{}语句块详解

    static{}(即static块),会在类被加载的时候执行且仅会被执行一次,一般用来初始化静态变量和调用静态方法,下面我们详细的讨论一下该语句块的特性及应用. 一.在程序的一次执行过程中,stati ...

  6. 深入探究javascript的 {} 语句块

    今日学习解析json字符串,用到了一个eval()方法,解析字符串的时候为什么需要加上括号呢?摸不着头脑.原来javascript中{}语句块具有二义性,不加括号会出错,理解这种二义性对我们理解jav ...

  7. java synchronized静态同步方法与非静态同步方法,同步语句块

    摘自:http://topmanopensource.iteye.com/blog/1738178 进行多线程编程,同步控制是非常重要的,而同步控制就涉及到了锁. 对代码进行同步控制我们可以选择同步方 ...

  8. 关于java的static语句块

    声明:转载请注明出处 static{}(即static块),会在类被加载的时候执行且仅会被执行一次,一般用来初始化静态变量和调用静态方法,下面我们详细的讨论一下该语句块的特性及应用. 一.在程序的一次 ...

  9. C++@语句块

    #include <iostream> using namespace std; int main() { { int x=1; cout << x << endl ...

  10. Firefox 对条件判断语句块内的函数声明的处理与其他浏览器有差异

    标准参考 函数声明和函数表达式 定义一个函数有两种途径:函数声明和函数表达式. 函数声明: function Identifier ( FormalParameterList opt ) { Func ...

随机推荐

  1. Flink - Scheduler

    Job资源分配的过程, 在submitJob中,会生成ExecutionGraph 最终调用到, executionGraph.scheduleForExecution(scheduler) 接着,E ...

  2. WIN7环境变量path误删(windows找不到文件‘%windir%\systempropertiesadvanced.exe’)的解决办法

    一.进入安全模式 1.通过Ctrl+R打开运行窗口,输入Msconfig 2.如上图,选择安全引导,点击确定.重启计算机进入安全模式. 二.在安全模式下,设置环境变量 1.C:\Windows\Sys ...

  3. BZOJ4391 High Card Low Card [Usaco2015 dec](贪心+线段树/set库

    正解:贪心+线段树/set库 解题报告: 算辣直接甩链接qwq 恩这题就贪心?从前往后从后往前各推一次然后找一遍哪个地方最大就欧克了,正确性很容易证明 (这里有个,很妙的想法,就是,从后往前推从前往后 ...

  4. Java中包装类型和基本类型的使用场景(什么时候使用包装类型)(转)

    说明:最简单的理解,基本类型有默认值,而包装类型初始为null.然后再根据这两个特性进行分业务使用,在阿里巴巴的规范里所有的POJO类必须使用包装类型,而在本地变量推荐使用基本类型. Java语言提供 ...

  5. 01.jupyter环境安装

    jupyter notebook环境安装 一.什么是Jupyter Notebook? 1. 简介 Jupyter Notebook是基于网页的用于交互计算的应用程序.其可被应用于全过程计算:开发.文 ...

  6. Asp.net Mvc action返回多个模型实体给view

    1.controller中action代码: public class HomeController : Controller { public ActionResult Detail(int id) ...

  7. oracle查看哪些表被锁

    select b.owner,b.object_name,a.session_id,a.locked_mode from v$locked_object a,dba_objects b where a ...

  8. windows安装nginx并存放静态资源

    1.将nginx-windows.zip下载下来,然后点击nginx.exe 如果一闪而过并且打开网页输入localhost显示无法访问,打开error.log文件:No mapping for th ...

  9. 要继续看Python写算法的内容请到那里去

    由于在这里发文章的时候.莫名其妙的出现公布出去的问题.客服告知是由于链接或者敏感词. 能不能告诉我哪里出了问题?我能够改动,以便再发. 可是,没有人告诉我.仅仅是告诉我不能发. 另外,能不能公布一下敏 ...

  10. 在Windows Server 2008的桌面上显示“我的电脑”“网上邻居”等图标?

    装完windows server2008 r2 x64后发现桌面只有一个“回收站”图标,如何把“我的电脑”“网上邻居”等图标添加到桌面呢?操作步骤: 1. 点击 开始 在搜索中输入 icon 2. 点 ...