Java中关于try catch finally中的问题总结

关于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、机房断电、手残按在电源键、脚残踢断插座、服务器硬件故障等【无厘头的原因】
缘由总结分类:
  1. 程序执行在try catch 代码中后进入死循环操作(1.正常的业务逻辑,2.程序bug导致);
  2. 程序执行在try catch 代码后线程阻塞停止执行(1.死锁现象,2.进程Crash);
  3. 程序执行在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中抛出异常(没有补货)结果是整个函数异常,这样就没有任何返回值了。

总结:

  1. try{} catch{}finally{}的情况中,程序在执行到return完毕后,整个方法的返回值就已经确定,由于还要执行finally代码块,因此程序会将返回值暂存在局部变量区,开辟新的操作数栈用来执行finally语句块中代码,在finally执行完毕,然后将暂存的返回值又复制回操作数栈顶返回;详细参考链接
  2. 在finally的设计初衷是用来释放资源等收尾工作,finally中尽量不要执行核心业务逻辑代码,建议在finally中处理里做一些 释放资源、记录日志等工作,如果finally中有出现异常的可能的代码一定要try catch。
三、try catch 的性能问题;

关于Java中try catch对性能影响的问题是一直存在争论的,为什么会一直存在这个争论,个人认为是因为:

“要在争论中打败无知的人是不可能的”

即主要原因是部分开发人员的 不严谨的测试流程不得当的测试方法 ,导致测试得出的 错误结论而不自知 ,并且手持错误结论一直 “据理力争”

根据个人基本认识和基本科学方法,个人比较推荐以下博文:
try catch 对性能影响
Java上的try catch并不影响性能 或者 参考链接
只推荐上面的文章并是说网上其他的博文都不好,而是刚好看到这两篇博文,个人认为写的不错;而且个人自知水平能力有限,难以得出准确结论,而且个人比较认同他们的测试方法。

个人初步结论: 个人比较认同try catch对性能的影响微乎其微的观点,而且对于异常进行相应的处理引起的性能消耗,来换取对程序的健壮性和安全性的保证个人认为是十分划算的。
当然这并不意味着可以滥用try catch,而是在代码不确定的地方使用,同时建议尽量在小范围内使用try catch,而且catch中的异常尽可能详细方便后期查找,更建议优先考虑程序的健壮性和安全性。

四、欢迎诸位批评指正;

由于个人本身就是半路出家的开发,计算机和编程基础知识浅薄,而且目前工作经验相对欠缺,所以文中难免有纰漏错误之处,望诸位同行朋友海涵不吝赐教,本人不胜感激;

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java try-catch-finally 语句用于捕获和处理异常。它的基本语法如下: ```java try { // 可能会抛出异常的代码块 } catch (ExceptionType1 e1) { // 处理异常类型1的代码块 } catch (ExceptionType2 e2) { // 处理异常类型2的代码块 } finally { // 无论是否发生异常,都会执行的代码块 } ``` 在 try,你可以放置可能会抛出异常的代码。如果在执行 try的代码时发生了异常,那么就会跳到相应的 catch进行异常处理。catch 块可以有多个,每个 catch 块用于捕获不同类型的异常,并提供相应的处理逻辑。catch的参数 e1、e2 是异常对象,你可以使用它们来获取有关异常的信息。 无论是否发生异常,finally的代码都会被执行。finally 块通常用于释放资源或执行清理操作,确保在任何情况下都会执行。 如果在 try发生了异常,并且没有相应的 catch 块来处理该异常,那么该异常将被传递给上层调用栈,直到找到合适的 catch 块进行处理,或者如果没有找到任何 catch 块,则程序将终止。 以下是一个简单的示例: ```java try { int result = divide(10, 0); System.out.println("结果:" + result); } catch (ArithmeticException e) { System.out.println("除数不能为零!"); } finally { System.out.println("finally的代码"); } public static int divide(int dividend, int divisor) { return dividend / divisor; } ``` 在上面的示例,divide 方法会抛出一个 ArithmeticException 异常,因为除数为零。在 catch,我们对该异常进行处理,并输出相应的信息。无论是否发生异常,finally的代码都会执行,输出 "finally的代码"。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值