关于try catch finally中的几个问题基本上都是为了应对面试的,当然有些也是为了加深认识。
一、try catch finally中finally中代码不执行的情况
1.try catch 中存在死循环[while(true)死循环],而且代码中不会抛出异常;
- 正常的代码: 类似的例子如Android主线程中Handler的Looper循环线程一样;
- 程序中bug: 当然也可能是程序中业务逻辑bug导致死循环,这样就是这条线程一直循环,程序出口锁死类型的bug;
2.在try catch 的代码块中发生死锁,线程在try catch代码块中永久阻塞啦;
- 当然这也应该属于bug类型的情况,因为实在想不出什么场景有这样的需求;
3.在线程的中代码块执行到try catch 时,进程中执行了JVM退出代码[主动退出];
常见的主动退出代码有:
- System.exit(int status);
- Runtime.getRuntime().exit(int status);
- Runtime.getRuntime().halt(int status);
- 运维直接输入Ctrl+C快捷操作等其他主动退出JVM的操作
4.在守护线程[DaemonThread]中代码块执行到try catch 时,所有的用户线程执行完毕,JVM直接杀死线程;
- 基本知识点:守护线程不能单独存活在JVM,即当程序中用户线程全部结束后JVM会立即杀死所有守护线程
- 这条有点类似上一条,不同的是由JVM机制杀死App的,不是开发者控制的;
5.在线程的中代码块执行到try catch 时,发生异常JVM退出[异常退出]
异常分为:
应用内异常
和其他异常
应用内异常属于可控异常:
- 代码块执行到try catch 时,应用内其他线程发生异常【未捕获、捕获失败】导致进程退出;例如:RuntimeException()、OOM等;
其他异常属于不控异常【和代码无关的异常,有点无厘头】
- 代码块执行到try catch 时,发生不可控异常导致JVM退出;例如:服务器系统Crash、机房断电、手残按在电源键、脚残踢断插座、服务器硬件故障等【无厘头的原因】
缘由总结分类:
- 程序执行在try catch 代码中后进入死循环操作(1.正常的业务逻辑,2.程序bug导致);
- 程序执行在try catch 代码后线程阻塞停止执行(1.死锁现象,2.进程Crash);
- 程序执行在try catch 代码时,出行不可控行为或者异常(1.用户线程全部执行完成,JVM直接杀死守护线程;2.发生了与代码无关的外部环境异常);
二、try catch finally与return执行的情况
这也是面试题中的常客,一切还是先代码验证一下吧:
验证代码如下:
//用来抛出异常的
private static List list;
private static String tryCatch() {
String result=null;
try {
list.clear();//用来抛异常的
System.out.println("try --------- >");
result="Try-->";
return result;
} catch (Exception e) {
System.out.println("exception --------- >");
result="Exception -->";
return result;
} finally {
// list.clear();//用来抛异常的
System.out.println("finally --------- >");
result="Finally -->";
// return "Finally -->";
}
// System.out.println("last ------->");
//result="Last return -->";
// return "Last return -->";
}
上面代码执行有简单修该一下就可以实现面试中常见的组合方式,但是究其所以都遵循同样的原则,至于各种组合和验证代码,就是so easy了,在此不一一列举,如果有不明白的可以参考try catch finally中return情况然后自己组合测试,如果还不明白那就放弃吧。
测试结论 :
- 1.在任何情况下,如果finally存在的话,finally块中代码都会执行;只有在try catch中捕获到异常时,异常中的代码才会被执行,而且try catch中才可能有不部分代码不执行的情况;
- 2.在finally中没有return也没抛出异常时,只要在finally之前代码中已经执行过[return result ;]代码【无论return 是在trycatch中还是异常处理中执行的】,在执行完成finally后,函数返回值依然是之前return时的result 值,所以在finally代码中修改result 值是无效的;
- 3.无论是哪一种类型,如果finally中有return语句,无论在finally之前的代码块中有没有return以及result的值,函数会在执行到finally中的return后会函数立即返回此时的result的值;
- 4 .finally中的代码块中异常问题:如果在finally中抛出异常(没有补货)结果是整个函数异常,这样就没有任何返回值了。
总结:
- try{} catch{}finally{}的情况中,程序在执行到return完毕后,整个方法的返回值就已经确定,由于还要执行finally代码块,因此程序会将返回值暂存在局部变量区,开辟新的操作数栈用来执行finally语句块中代码,在finally执行完毕,然后将暂存的返回值又复制回操作数栈顶返回;详细参考链接;
- 在finally的设计初衷是用来释放资源等收尾工作,finally中尽量不要执行核心业务逻辑代码,建议在finally中处理里做一些 释放资源、记录日志等工作,如果finally中有出现异常的可能的代码一定要try catch。
三、try catch 的性能问题;
关于Java中try catch对性能影响的问题是一直存在争论的,为什么会一直存在这个争论,个人认为是因为:
“要在争论中打败无知的人是不可能的”
;
即主要原因是部分开发人员的 不严谨的测试流程
和 不得当的测试方法
,导致测试得出的 错误结论而不自知
,并且手持错误结论一直 “据理力争”
;
根据个人基本认识和基本科学方法,个人比较推荐以下博文:
try catch 对性能影响
Java上的try catch并不影响性能 或者 参考链接
只推荐上面的文章并是说网上其他的博文都不好,而是刚好看到这两篇博文,个人认为写的不错;而且个人自知水平能力有限,难以得出准确结论,而且个人比较认同他们的测试方法。
个人初步结论: 个人比较认同try catch对性能的影响微乎其微的观点,而且对于异常进行相应的处理引起的性能消耗,来换取对程序的健壮性和安全性的保证个人认为是十分划算的。
当然这并不意味着可以滥用try catch,而是在代码不确定的地方使用,同时建议尽量在小范围内使用try catch,而且catch中的异常尽可能详细方便后期查找,更建议优先考虑程序的健壮性和安全性。
四、欢迎诸位批评指正;
由于个人本身就是半路出家的开发,计算机和编程基础知识浅薄,而且目前工作经验相对欠缺,所以文中难免有纰漏错误之处,望诸位同行朋友海涵不吝赐教,本人不胜感激;