你真的知道吗?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 ...
随机推荐
- 从原理到应用,人人都懂的ChatGPT指南
作者:京东科技 何雨航 引言 如何充分发挥ChatGPT潜能,已是众多企业关注的焦点.但是,这种变化对员工来说未必是好事情.IBM计划用AI替代7800个工作岗位,游戏公司使用MidJourney削减 ...
- SQL语句获取数据表结构定义,适合导出EXCEL为文档
SELECT 表名 = Case When A.colorder=1 Then D.name Else '' End, 表说明 = Case When A.colorder=1 Then isnull ...
- Java设计模式【单例模式】
Java设计模式[单例模式] 单例模式 单例模式(Singleton Pattern)是一种创建型设计模式,其主要目的是确保一个类只有一个实例,并提供对该实例的唯一访问点. 优缺点 优点: 提供了对唯 ...
- 都说DevOps落地难,到底难在哪里?也许你还没找到套路
当你打开这篇文章的时候,也许你也在为DevOps的落地而苦恼,也许你的组织正在尝试DevOps转型,作为一线的实践者,说说我对这个"落地难"的看法,欢迎交流不同看法- DevOps ...
- 深入理解 python 虚拟机:魔术方法之数学计算
深入理解 python 虚拟机:魔术方法之数学计算 在本篇文章当中主要给大家介绍在 python 当中一些常见的魔术方法,本篇文章主要是关于与数学计算相关的一些魔术方法,在很多科学计算的包当中都使用到 ...
- 《Linux的文件目录类指令 20条》
文件目录类的指令 1.pwd指令 查看当前目录 2.ls 指令 查看当前目录所有内容信息 ls -a 显示当前目录所有的文件和目录,包括隐藏的 ls -l 以列表的方式显示信息 ls -al或la ...
- Error: Cannot find module ‘webpack-cli/bin/config-yargs‘
今配置一个webpack-dev-server进行服务端渲染时老是不正确 npm run dev 就崩了 起初的配置为 "devDependencies": { "web ...
- weex 中出现 loading无法关闭
如题使用weex 搞个app 一安装就有一个bug 一直这里转!!! 找了半天原来是自己没按规定来,在index.vue中直接使用了rower <template> <router- ...
- Kali系统 连接 Xshell
1> 进入kali系统,修改ssh配置文件:vi /etc/ssh/sshd_config 2> 将PermitRootLogin without-password修改为:PermitRo ...
- es mysql 适用场景对比
es mysql 适用场景对比 问题一 全文检索毫无疑问直接上es,那么除了这种场景,什么时候该选es?为啥mysql不行? 对枚举字段的搜索 mysql创建索引的原则是对于那些区别度高字段建立索引, ...