当try-catch-finally代码块遇上return,代码执行流程是怎样
这里打算用一个Java读取文件内容的例子来测试,文件存在,不抛异常,文件不存在,则抛出FileNotFoundException;
Java读取文件代码如下:
/**
* 根据路径和文件名获取内容
* @param filePath
* @param fileName
* @return
*/
public Object findFileContentByName(String filePath, String fileName) {
InputStream in = null;
Scanner scanner = null;
try {
in = new FileInputStream(filePath + "/" + fileName);
scanner = new Scanner(in);
StringBuffer stringBuffer = new StringBuffer();
if(scanner.hasNext()){
String s = scanner.nextLine();
stringBuffer.append(s).append("\n");
} log.info("stringBuffer.toString()");
return stringBuffer.toString(); }catch (FileNotFoundException e){
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
log.info("Close stream!");
try {
if(scanner != null){
scanner.close();
} if(in != null){
in.close();
}
}catch (IOException e){
e.printStackTrace();
} } log.info("Preparing return null");
return null;
}
代码很简单,就是传入文件的路径和文件名(包括文件后缀名),来获取文件内容;
当我们传入一个在该路径下存在的文件时,不会抛异常,日志如下图:

当我们传入一个不存在该路径下的文件时,会抛出异常,日志如下图(堆栈信息太长只截取了部分):


当我们在catch语句块中加入了return,这时我们传入一个不存在该路径下的文件时,会抛出异常,执行完finally(不要在finally代码会中写return)会立即执行catch中的return,则该函数终止:
public Object findFileContentByName(String filePath, String fileName) {
InputStream in = null;
Scanner scanner = null;
try {
in = new FileInputStream(filePath + "/" + fileName);
scanner = new Scanner(in);
StringBuffer stringBuffer = new StringBuffer();
if (scanner.hasNext()){
String s = scanner.nextLine();
stringBuffer.append(s).append("\n");
}
log.info("stringBuffer.toString()");
return stringBuffer.toString();
}catch (FileNotFoundException e){
log.info("catch FileNotFoundException e");
e.printStackTrace();
return "catch FileNotFoundException e";
} catch (IOException e) {
e.printStackTrace();
} finally {
log.info("Close stream!");
try {
if(scanner != null){
scanner.close();
}
if(in != null){
in.close();
}
}catch (IOException e){
e.printStackTrace();
}
// 不要在finally块中使用return,finally块中的return返回后方法结束执行,不会再执行try块中的return语句。
}
log.info("Preparing return null");
return null;
}


总结
在try-catch-finally代码块中,有多个return时:
如果代码没有抛出异常,以第一个return返回(本例中的return在try中),并且finally代码块还会被执行;
如果代码块抛出异常,应该也是以第一个return返回,并且finally代码块还会被执行;
finally代码块的执行不一定是最后执行的,比如本例子中,由于抛出异常后,无return,接着执行finally,finally代码块执行完后,函数还有代码,打印了日志,然后return null。
总的来说,不管代码有没有抛出异常,代码块执行的顺序是:
如果代码执行到第一个return时,未执行finally代码块,则执行完第一个return,紧接着执行finally代码块,执行完finally后,不再执行该函数任何代码;
如果代码执行到第一个return时,已经执行完finally代码块,则紧接着执行第一个return后,不再执行该函数任何代码;
如果finally函数代码块后面没代码,则执行finally代码块后,不再执行该函数任何代码;
注意:第一个return不是函数代码的顺序,而是代码执行过程中遇到的第一个return!
不要在finally块中使用return,finally块中的return返回后,方法结束执行,不会再执行try块中的return语句。
当try-catch-finally代码块遇上return,代码执行流程是怎样的更多相关文章
- final、static、代码块、静态代码块、内部类、代码执行顺序
final final域使得确保初始化安全性(initialization safety)成为可能,初始化安全性让不可变形对象不需要同步就能自由地被访问和共享 作用在类上 ...
- 关于java构造函数,静态代码块,构造代码块,和普通代码块相关总结(一)
构造函数.构造代码块和静态代码块容易混淆,它们的执行条件和执行顺序也常常容易犯迷.这里就针对这些问题说一下我个人的一些理解,顺便对这部分内容做个小结. 一.构造函数 格式:类名(参数1,参数2,-){ ...
- java中静态代码块,构造代码块,以及构造方法的执行顺序
写了许久的代码,却把一些基础的东西都给忘了,今天无聊就顺手写了个,然后测试下,发现跟我记忆中的竟然有些出入,作为一个两年的开发,我感觉自己很失败啊. 父类pojo: public class Pojo ...
- java 代码块,静态代码块,构造器等的执行顺序
写了一段测试代码,如下: public class ExecutionSequence extends fatherClass{ static{ System.out.printl ...
- java中普通代码块,构造代码块,静态代码块的区别及代码示例
本文转自:http://www.cnblogs.com/sophine/p/3531282.html 执行顺序:(优先级从高到低)静态代码块>main方法>构造代码块>构造方法. 其 ...
- 构造代码块、构造函数、this执行顺序
一.构造函数 对象一建立就会调用与之对应的构造函数. 构造函数的作用:可以用于给对象进行初始化. 构造函数的小细节:当一个类中没有定义构造函数时,系统会默认给该类加一个空参数的构造函数:当在类中自定义 ...
- JAVA程序执行顺序(静态代码块》非静态代码块》静态方法》构造函数)
总结:静态代码块总是最先执行. 非静态代码块跟非静态方法一样,跟对象有关.只不过非静态代码块在构造函数之前执行. 父类非静态代码块.构造函数执行完毕后(相当于父类对象初始化完成), 才开始执行子类的非 ...
- java中静态代码块,非静态代码块,构造函数
关于静态代码块 静态代码块的写法: static { System.out.println("我是静态代码块"); } 静态代码块的特点: 1.执行优先级高于非静态的初始化块,它会 ...
- try、catch、finally--try块里有return,finally还执行吗?
finally块的作用是,保证无论出现什么情况,finally块里的代码一定会被执行. 由于程序执行return就意味着结束对当前函数的调用并跳出这个函数体,所以任何语句要执行都只能在return之前 ...
随机推荐
- day6需要记忆(元组字典集合)
一:基本使用:(元组 tuple)优先掌握的操作1.按索引取值(正向取+反向取):只能取2.切片(顾头不顾尾,步长)3.长度 len()4.成员运算in和not in5.循环需要掌握的操作1.cou ...
- .Net Web下 Console输出
.NET winform的时候,一直都是用 Console.Write向控制台输出信息的,但是在Web中是输出不了的. web程序执行时,是被附加到IIS进程的一个单独的AppDomain中的,所以就 ...
- hive表命名规范 源码规则
tablename 进来前已经把"`","."等过滤掉了,所以就是单词字符喽 \w搞定 \w包含_ 哈哈 规范就是 a-z A-Z 0-9 _ 也就是传说中的单 ...
- spark sql 中的结构化数据
1. 连接mysql 首先需要把mysql-connector-java-5.1.39.jar 拷贝到 spark 的jars目录里面: scala> import org.apache.spa ...
- Node Koa2 完整教程
请移步 http://cnodejs.org/topic/58ac640e7872ea0864fedf90
- day11-mysql中的mysql数据库不见了
mysql中的mysql数据库不见了 昨天刚刚在vmware虚拟机的linux上安装mysql,今天登上就发现一个问题.通过网上漫长的寻找,终于解决了.所以我在这把我解决的步骤跟大家分享一下. 问题就 ...
- xampp默认mysql数据库root密码的修改
因为安装xampp后的mysql默认用户root的密码为空,而比如部署Testlink时需要提供数据库密码,此时就需要给root设定密码(网上有些方法,大同小异,但是可能都未标明关键点,未一些出上手的 ...
- vue - @click 用到的修饰符
1.vue提供的方法 .stop .prevent .capture .self .once .passive <!-- 阻止单击事件继续传播 --><a v-on:click.st ...
- js 编写一个神奇的四则运算
写一个算法,有时候可以用简单的方法就可以写出来,但是只能针对特定的环境,如果要能够适应不同的环境,就需要对算法进行优化,在优化的过程中,你会觉得非常神奇,下面来看一个简单的四则运算的算法编写方式: 1 ...
- python语言中的数据类型
一.内存管理 1.python解释器的垃圾回收机制 垃圾:当一个值上没有人绑定任何变量名时(当引用计数为0),该值就是一个垃圾. python解释器运行时会检测值的引用计数,当引用计数=0该值会被清除 ...