你真的知道吗?catch、finally和return哪个先执行
我的一位朋友前阵子遇到一个问题,问题的核心就是try……catch……finally中catch和finally代码块到底哪个先执。这个问题看起来很简单,当然是“catch先执行、finally后执行”了?真的是这样吗?
有下面一段C#代码,请问这段代码的执行结果是什么?
public static void Main(string[] args)
{
try
{
A();
}
catch
{
Console.WriteLine("catch!!!");
}
}
static void A()
{
try
{
throw new Exception();
}
finally
{
Console.WriteLine("finally!!!");
}
}
A()方法的try代码块中抛出了异常,而A方法没有处理这个异常,所以Main方法的catch代码块会捕获这个异常,但是A()方法中又有finally代码块,那么到底是异常抛出后先执行Main方法的catch代码块呢还是先执行A()方法中的finally代码块呢?运行一下程序就能看出来,是finally代码块执行,结果如下所示。
finally!!! catch!!!
为什么呢?这需要从方法调用的异常对象如何传递给被调用方法讲起。在一段代码调用一个方法的时候,被调用的方法会把返回值、异常对象等放到一个特定的位置,这个位置叫做Stack Frame,调用者代码会从这个特定的位置获得被调用方法的返回值、异常对象等信息。因此,无论是throw异常的时候还是return返回值的时候,被调用的方法只是把异常对象或者返回值放到了这个特定的位置,在return或者throw执行之后,如果方法中还有finally等没有执行完成的代码,那么这些代码仍然会在return、throw之后继续执行,然后方法执行才会结束,之后调用这个方法的代码才会从Stack Frame中读取到返回值或者获取到被调用的方法抛出的异常对象。因此,上面的代码才会先执行finally然后才执行catch。
明白了这个道理,请回答一下,下面代码的执行结果是什么?
public static void Main(string[] args)
{
try
{
A();
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
}
static void A()
{
try
{
throw new Exception("aa");
}
finally
{
throw new Exception("bb");
}
}
上面这是一段很特殊的代码,在try代码块中抛出了一个异常(信息是aa),在finally中也抛出了一个异常(信息是bb),那么程序实际打印出来的异常信息是什么呢?上面程序执行结果是“bb”。通过上面的分析不难理解其原理:try代码块中的throw new Exception("aa")把方法的异常对象设置为Exception("aa"),而finall代码块中的throw new Exception("bb")又把方法的异常对象修改为Exception("bb"),因此最终方法抛出的异常对象是Exception("bb")。
接下来,我们再来捉弄一下方法的返回值,我们尝试在finally代码块中修改方法的返回值。不幸的是(也可以说,幸运的是),C#禁止我们在finally代码块使用return语句,不过我们可以在Java中做这样的尝试,如下Java代码所示:
public static void main(String[] args)
{
System.out.println(A());
}
static int A()
{
try
{
return 1;
}
finally
{
return 2;
}
}
我们在try代码块中通过return 1把方法的返回值设置为1,但是在finally代码块中又把方法的返回值设置为2,因此方法的最终返回值就是2。
综上所述,一个方法中通过return设定返回值或者throw抛出异常的时候,方法并没有立即返回,只是在Stack Frame上保存了这个返回值或者异常对象,然后会继续执行finally中的代码,如果我们在finally代码块中修改了返回值或者抛出了新的异常,那么最终的调用中获得的返回值或者捕获的对象就是修改后的返回值或者异常对象。
你真的知道吗?catch、finally和return哪个先执行的更多相关文章
- try,catch,finally含return时的执行顺序及丢失的伪例
最近面试遇到一个之前也看到过但没去看一下的问题.就是有return情况下的try,catch,finally的执行顺序. 今天写了下. 先看顺序问题.总结如下: 一:finally中没有写return ...
- 再问你一遍,你真的了解try..catch(finally)吗???
定义 首先来看下 MDN 的定义: The try...catch statement marks a block of statements to try and specifies a respo ...
- try--catch--finally中return返回值执行的顺序(区别)
1.try块中没有抛出异常,try.catch和finally块中都有return语句 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public static int ...
- try--catch--finally中return返回值执行的顺序
1.try块中没有抛出异常,try.catch和finally块中都有return语句 public static int NoException(){ int i=10; try{ System.o ...
- Java finally语句是在try或catch的retrurn之前还是之后执行
若try或catch中没有return语句,则按正常执行流,从上到下,finally里的所有修改都生效. 这里讨论的是try或catch里有return或throw语句的情形,此情形比较让人迷惑. 总 ...
- Java中try catch finally语句中含return语句的执行情况总结-编程陷阱
前言:有java编程基础的人对java的异常处理机制都会有一定了解,而且可能感觉使用起来也比较简单,但如果在try catch finally语句块中遇到return语句,开发者可能就会遇到一些逻辑问 ...
- 【转】Java中try catch finally语句中含有return语句的执行情况(总结版)
Java中try catch finally语句中含有return语句的执行情况(总结版) 有一点可以肯定,finally块中的内容会先于try中的return语句执行,如果finall语句块中也有r ...
- java中 try catch finally和return联合使用时,代码执行顺序的小细节
代码1测试 public static void main(String[] args) { aa(); } static int aa() { try { int a=4/0; } catch (E ...
- try、catch、finally都有return语句时执行哪个
任何执行try 或者catch中的return语句之前,都会先执行finally语句,如果finally存在的话.如果finally中有return语句,那么程序就return了,所以finally中 ...
- Java_try,catch,finally return之间的执行顺序
以往认为函数只要执行到return语句便会返回结果并终止,然而这时错误的,因为这存在特例. 掌握下面几条原则就可以完全解决“当try.catch.finally遭遇return”的问题. 原则:1.f ...
随机推荐
- Codeforces Round #844 (Div. 1 + Div. 2, based on VK Cup 2022 - Elimination Round) 小记
在机房其它人都有许多的橙名小号后我终于大号上橙了(果然还是太菜了),写篇博客记录一下. 计数水平太弱,赛场最后 5 分钟乱糊了一个 F 的做法,后来发现其它人做法都短好多. A & B &am ...
- ET中热更(ILRuntime)使用过程中,需要做的适配器,比如Linq排序
ET中热更(ILRuntime)使用过程中,需要做的适配器,比如Linq排序 By Flamesky 最近项目中用到个Linq的排序,由于没有注册适配器,导致不能用,其实ILRT作者已经做得很好,报错 ...
- JavaScript 如何判断一个对象中是否有某个属性?
今天讲讲,JavaScript 如何判断一个对象中是否有某个属性? 我总结了5个方法: 方法1: if(Obj[a]) {} 缺点:对于参数值为 undefined 和 0 的无效. 方法2: if( ...
- 2020-10-15:mysql的双1设置是什么?
福哥答案2020-10-15:#福大大架构师每日一题# [答案来自知乎:](https://www.zhihu.com/question/425704691) 其实就是innodb_flush_log ...
- 2022-02-22:机器人大冒险。 力扣团队买了一个可编程机器人,机器人初始位置在原点(0, 0)。小伙伴事先给机器人输入一串指令command,机器人就会无限循环这条指令的步骤进行移动。指令有两种
2022-02-22:机器人大冒险. 力扣团队买了一个可编程机器人,机器人初始位置在原点(0, 0).小伙伴事先给机器人输入一串指令command,机器人就会无限循环这条指令的步骤进行移动.指令有两种 ...
- 反向传播(Backpropagation)相关思想
在前面我们学习了SVM损失函数和softmax损失函数,我们优化权重矩阵w的具体思路便是让损失函数最小化,还记得损失函数的定义吗? 没错,损失函数长这样,其中,Wj为权重矩阵的第j个列向量,xi为第i ...
- Mdnice 简洁主题
Md2All 是个人非常喜欢的一个 Markdown 排版工具,也是一直以来本公众号推文排版编辑的主要阵地.但发现 Md2All 有时候会非常卡(不太清楚是不是 Md2All 用了国外的服务器),而且 ...
- 安装指定版本的mysql(mysql5.7)
安装指定版本的mysql(mysql5.7) 目标:解决需求,安装mysql5.7 前言: 安装软件的三种方式: rpm 安装 源代码编译安装 yum仓库安装 本地光盘 阿里云yum源 自建yum仓库 ...
- 【python基础】函数-参数形式
鉴于函数定义中可能包含多个形参变量,因此函数调用中也可能包含多个实参变量.向函数传递实参变量给形参变量的方式有很多,可使用位置参数,这要求实参变量的顺序与形参变量的顺序相同:也可使用关键字参数,都由变 ...
- 快速上手kettle(四)壶中可以倒出些啥?
目录 前言 一 .kettle 这壶里能倒出啥? 二 .Access输出 2.1 Access输出设置 2.2 启动转换,查看输出 三 .Excel输出 3.1 选择excel扩展名 3.2 1 将表 ...