找工作时,有这样一道题:

try{}里面有一条return语句,那么紧跟在这个try后的finally{}里的代码会不会执行,什么时候执行,在return之前还是之后?

我没有怎么思考,根据脑子里仅有的一点异常知识,给出了下面的解:

如果try{}没有抛出异常,那么finally{}里的代码不会执行。

如果try{}抛出异常,那么finally{}里的代码会执行,在return之前。

借助下面的代码验证一下:

 private static int testFinally() {
try {
System.out.println("Try!");
return 1;
} finally {
System.out.println("Finally!");
}
}

毫无疑问,输出的结果显示上述解是草率的,是错的。那么,正解是什么?其实,读书用心点的话,可以注意到《Core Java》上的这段话:

Suppose you exit the middle of a try block with a return statement. Before the method returns, the finally block is executed. If the finally block also contains a return statement, then it masks the original return value.

——摘自《Core Java, Volume I: Fundamentals》

这段话就是正解。当方法中抛出异常,或包含break,continue,return语句时,方法就无法按照正常的方式终止。一般地,在try-finally结构中,当try部分意外终止时,并不意味着结束,方法仍然会继续执行finally部分。也就是说,上述代码返回1之前,会先打印“Finally!”。如果问原因,真说不出什么,没什么道理,Java就是这么干的。就和学英语遇到陌生的词组解释不了时,用“固定搭配”来安慰自己,是同一个道理。

进一步地,有没有某种情况,finally{}不会执行?另一个例子:

 private static void testFinally() {
try {
System.out.println("Try!");
System.exit(0);
} finally {
System.out.println("Finally!");
}
}

System.exit(0)可以阻止执行finally语句块。之所以可以做到,是因为System.exit()方法会立即终止当前正在运行的 Java 虚拟机。我们知道,在Java中,源码首先被编译成字节码,然后由虚拟机解释执行class文件。虚拟机进程被杀死后,程序当然无法接着执行下去。

众所周知,在需要关闭一些资源时,使用Finally语句是一种不错的选择。下面介绍一种结合try-catch和try-finally的方式:

 InputStream in = ...;
try{
try{
// [1]Code may throw excption.
}finally{
in.close();  //[2]
}
}catch(IOException e){
// [3]handle exception.
}

在这种方式中,内存的try语句块只有一个职责,就是关闭输入流。外层的try语句块也只有一个职责,就是捕获可能出现的异常。职责相当明确,结构相当清晰。但是,这种方式也存在潜在的错误:如果[2]处在关闭输入流时也抛出了IOException,那么[3]处捕获的异常究竟是[1]处抛出的,还是[2]处抛出的。事实上,若出现上述情况,则[3]处实际捕获到[2]处抛出的异常,会忽略[1]处抛出的异常。这是需要小心的地方!

以上是对异常,尤其是Finally语句易错点的总结,仅供参考。

由一道面试题想到的:Finally的更多相关文章

  1. 一道面试题:按照其描述要求用java语言实现快速排序

    回来想了想,写出了如下的程序: /** * 一道面试题,按照其描述要求进行快速排序(英文的,希望理解是对的..) * 要求:和一般的快速排序算法不同的是,它不是依次交换pivot和左右元素节点(交换2 ...

  2. 一道面试题与Java位操作 和 BitSet 库的使用

    前一段时间在网上看到这样一道面试题: 有个老的手机短信程序,由于当时的手机CPU,内存都很烂.所以这个短信程序只能记住256条短信,多了就删了. 每个短信有个唯一的ID,在0到255之间.当然用户可能 ...

  3. PHP递归创建多级目录(一道面试题的解题过程)

    今天看到一道面试题,要写出一个可以创建多级目录的函数: 我的第一个感觉就是用递归创建,具体思路如下: function Directory($dir){ if(is_dir($dir) || @mkd ...

  4. 关于Java类加载双亲委派机制的思考(附一道面试题)

    预定义类加载器和双亲委派机制 JVM预定义的三种类型类加载器: 启动(Bootstrap)类加载器:是用本地代码实现的类装入器,它负责将 <Java_Runtime_Home>/lib下面 ...

  5. 一道面试题比较synchronized和读写锁

    一.科普定义 这篇博文的两个主角“synchronized”和“读写锁” 1)synchronized 这个同步关键字相信大家都用得比较多,在上一篇“多个线程之间共享数据的方式”中也详细列举他的应用, ...

  6. <转>一道面试题比较synchronized和读写锁

    一.科普定义(原文:http://903497571.iteye.com/blog/1874752) 这篇博文的两个主角“synchronized”和“读写锁” 1)synchronized 这个同步 ...

  7. Java中有关构造函数的一道笔试题解析

    Java中有关构造函数的一道笔试题解析 1.详细题目例如以下 下列说法正确的有() A. class中的constructor不可省略 B. constructor必须与class同名,但方法不能与c ...

  8. 【C#基础知识】静态构造函数,来源于一道面试题的理解

    看到园友的一道面试题,很好奇,测试了一下结果. public class A { public static int X=B.Y ; public A() { ++X; } } public clas ...

  9. 一道笔试题来理顺Java中的值传递和引用传递

      题目如下: private static void change(StringBuffer str11, StringBuffer str12) { str12 = str11; str11 = ...

随机推荐

  1. WinForm、wpf、silverlight三者关系

    最近在学C#.NET,基本语法学习的差不多了,接下来准备学习图形界面设计部分.但是我目前对于.NET的WinForm.wpf.silverlight这三者的关系弄的不是很清楚,一般书中很少介绍wpf和 ...

  2. 左右xcode的重构选项的一些理解

    Rename(重命名):对标示符进行重命名,以获得更好的代码可读性,这些标示符包含类,方法或者函数的名称. Extract(抽取):将你在XCode种选择的代码抽取到一个新的方法或函数中. Creat ...

  3. 为什么tap事件绑定在document上,而不是对象本身上

    1.在移动端前端开发,click事件有300ms的延时,为了提升用户体验,快速响应.zepto添加了tap事件.tap是在手指触屏横纵向移动距离小于30px,触发tap事件.移动距离的判断是通过tou ...

  4. 关于委托:异常{ 无法将 匿名方法 转换为类型“System.Delegate”,因为它不是委托类型 }

    异常{ 无法将 匿名方法 转换为类型"System.Delegate",因为它不是委托类型 } 委托实际上是把方法名作为参数,但是若有好多个方法时,就要指明是哪个参数  查看如下代 ...

  5. TCP和UDP的差别

    简单的差别: TCP提供面向连接的.可靠的数据流传输,而UDP提供的是非面向连接的.不可靠的数据流传输. TCP传输单位称为TCP报文段,UDP传输单位称为用户数据报. TCP注重数据安全性,UDP传 ...

  6. mtk硬件项目开始关闭蓝牙功能:mtk 硬件ScanCode和keycode应用演示示例

    项目要求:该项目因为没有使用android5.0,导致启动bluetooth的蓝牙audio slave功能必须使用第三方模组,该第三方模组,启动是通过android主板通过GPIO控制.UI界面是通 ...

  7. 交叉编译libxml2

    请勿用于商业用途,转载请注明出处! xml的优势就是可以方便的管理配置项,libxml2是c语言实现的xml管理库,眼下项目须要ARM下的版本号,libxml2编译过程例如以下: 0.准备工作 下载地 ...

  8. 从头开始编写项目Makefile(八):型号规则

    [版权声明:转载请保留源:blog.csdn.net/gentleliu.Mail:shallnew at 163 dot com]     上创建的文件夹谈及.没有生产目标文件到相应的文件夹,在这里 ...

  9. cocos2d-x路~使得第一个字游戏(一个)

    前言 去年的回忆.另外,在第三.他们开发了他们的第一场比赛四月,它是游戏.所以我决定走上独立开发的道路上.了.第一款游戏达到它应有的盈利水平.然而这款游戏开发后的时间里.都没再取得还有一款令自己惬意的 ...

  10. 【Nginx】磁盘文件写入飞地发

    文章继续.什么时候Nginx当用户请求一个文件,这将无法读取该文件的内容加载到内存,然后从内存发送,但电话sendfile况下,从内核直接发送出去.这样做显然效率要更高.Nginx也为我们封装好了一系 ...