C# try-catch-finally throw-throws 你真的会了么?
try catch finally throw,throws 平时我们开发中用的很多,但是里面的具体执行顺序 发现自己还是不是很清晰,百度了一些博客,然后结合自己的实践,
总结了一下,便于自己以后查看。同时也希望对看到这篇文章的朋友有点帮助。如有错误请在评论区留言,谢谢。
首先我们简历控制台程序测试。
1-看第一种情况
执行结果:
然后catch中不抛异常
2-假设我们不想在fun1方法中处理异常,想把异常继续抛给调用者(这里指的是Main方法)让他们去处理这个异常,那么这时候就要用到throw,throws 了
将fun0 方法改造:
throw 的执行结果:
throw e的执行结果:
通过以上的结果我们可以总结到:
0-无论catch中有没有抛异常,finally中的代码块都会执行。
1-catch不使用throw / throws, 执行catch中的代码-》finally中的代码=》finally外部后续代码会继续执行=》方法结束
2-catch中使用throw / throws, 执行catch中的代码=》遇到了throw, throw后面的代码不执行了,然后执行finally中的代码,
执行完后回到catch中 通过throw 将代码抛给上一个直接调用层 方法直接结束。finally外部后续的代码也不执行了。
但是!我们发现上面的throw 和 throws都是返回的结果都是一样的 那么他们的执行结果到底是什么呢?
继续修改代码。
75行我们用throw / throw e两种写法
throw 结果:
显示了完整的堆栈信息,知道产生错误的最开始的那行代码位置。
throw e结果:
会在throw e的时候把之前的异常堆栈清空,然后只显示当前产生异常的代码位置。
总结:throw e会清空之前的异常堆栈,throw 会显示完整的堆栈信息。
在正常开发中我们可能写接一个接口会调用别人的信息,这时候你可能会提前判断可能会产生异常,这时候你可以有两种选择。
1-throw出去,让调用者自己去处理。2-你自己的catch代码块里面处理(比如记录日志啥的)。
我们来看下 如果throw e现实开发中会出现什么问题。
程序猿A 写了一个接口1 然后他预判到可能会有异常 然后在代码里面catch 然后throw e ,
这时候程序猿B 去调用了A的代码 报了异常,那这时候可能只会显示说A的那个接口方法出问题了,不会显示具体哪里出了问题。
这时候如果A的接口1 写了很复杂的逻辑 B通知A说 你快去看看你的接口为啥报异常了 那这时候A是不是很苦逼的分析代码,悔不当初啊。
所以A要么直接throw把完整的堆栈信息抛给掉的那一层, 要么直接自己处理异常(比如 将异常信息的堆栈信息记录在日志里面,那么到时候别人调用了A的接口出了问题是不是就可以通过看日志很快分析出原因了)所以都是一些细节问题,自己要注意。
--继续补充,说一下 catch 结合return的这种情况。
结果:
虽然finally里面改变了a的值但是返回的还是catch的a的值,说明catch返回a的时候已经确定了a的值所以finally改变a的值无效。
备注:finally 里面不能写return语句编译器会报错。
编译器对值类型a是这样处理的,那我们看下引用类型会发生什么。继续贴代码。
写法1:
输出结果:
写法2:
输出结果:
发现区别了么,说明在catch中返回值类型和引用类型,编译器处理的机制是不一样的。
最后以我自己的理解说下为什么要有finally这个关键字。因为finally不管有没有执行catch,finally都是会执行的。
在我们开发过程中,会有一些文件操作,数据库连接。如果报了异常,我们这时候肯定是要去关闭文件流的,以及将关闭数据库连接,然后将连接返回给数据库连接池,
这就是为什么我们经常强调说要在finally里面关闭文件流/关闭数据库连接,这样是为了怕批量发生异常的时候,不关闭文件流以及数据库连接那就会一直占用资源,
这样对我们应用服务器,数据库服务器性能产生不好的影响。所以要养成这种好习惯。
----End 转载请注明出处