【异常】浅析异常体系及为什么一定会执行finally块代码

异常体系:

        (1)所有异常(Exception)、错误(Error)都继承自异常中的基类:Throwable。而异常又可以分为检查异常(Checked Exception)、非检查异常(Unchecked Exception)两大类。

        (2)检查异常在编译期间由编译器检查的异常,编译器确保这些异常在编译期被处理,意味着不能直接使用关键字throw抛出异常,要么使用try、catch处理异常,要么在方法声明上使用throws关键字提醒方法调用者该方法可能会抛出的异常,让方法调用者处理异常。Exception从属子类中,除了RuntimeException类及其从属子类,其它子类都属于这一类型的异常。

        直接抛出检查异常:

        编译器直接报错,提示该异常需要处理。

        使用try、catch捕获异常:

        编译器不会报错,因为在catch块捕获了异常,并进行了处理(e.printStackTrace())。

        在方法签名上抛出异常:

        编译器不会报错,因为在调用该方法时,编译器会强制要求方法调用者使用try、catch捕获异常进行处理,或者继续通过throws关键字往上抛,让更上一层的方法调用者进行处理。

        (3)非检查异常编译器不会在编译期间就检查这类异常,直接抛出这类异常编译器不会报错,只有在程序运行时才可能抛出的异常。RuntimeException及其从属子类、Error及其从属子类都属于这类异常。

        直接抛出非检查异常:

        编译器不会报错,因为非检查异常只会在程序运行时才会进行相应处理。

        (4)如果想自定义检查异常,那么让类直接继承Exception类即可;如果想自定义非检查异常,那么让类直接继承自RuntimeException即可。

        自定义检查异常

        自定义非检查异常

异常处理机制:

        (1)try-catch字节码解析

       JavaCodes

public class TestMyException{public static void main(String[] args) {System.out.println("使用try、catch捕获自定义检查异常");try {throw new MyException();} catch (MyException e) {//将自定义检查异常封装成非检查异常throw new RuntimeException(e);}}
}
class MyException extends Exception{}

        ByteCodes

    Code:stack=3, locals=2, args_size=10: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;3: ldc           #3                  // String 使用try、catch处理检查异常5: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V8: new           #5                  // class com/hammajang/springbootdemo/entity/MyException11: dup                               //s 复制异常对象引用12: invokespecial #6                  // Method com/hammajang/springbootdemo/entity/MyException."<init>":()V15: athrow                            // 抛出MyException异常16: astore_1                          // 将捕获的异常对象存储在局部变量表中17: new           #7                  // class java/lang/RuntimeException20: dup                               // 复制异常对象引用21: aload_1                           // 将局部变量中的异常对象加载到操作数栈22: invokespecial #8                  // Method java/lang/RuntimeException."<init>":(Ljava/lang/Throwable;)V25: athrow                            // 抛出RuntimeException异常Exception table:from    to  target type8    16    16   Class com/hammajang/springbootdemo/entity/MyException

        Exception table含义如果执行指令8-指令16(try块)的过程中抛出了MyException类型的异常,则跳转到指令16(finally块)继续执行。

        (2)try-catch-finally字节码解析

        JavaCodes

public class TestMyException{public static void main(String[] args) {System.out.println("使用try、catch捕获自定义检查异常");try {throw new MyException();} catch (MyException e) {//将自定义检查异常封装成非检查异常throw new RuntimeException(e);} finally {System.out.println("TestMyException finally code...");}}
}

        ByteCodes

    Code:stack=3, locals=3, args_size=10: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;3: ldc           #3                  // String 使用try、catch捕获自定义检查异常5: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V8: new           #5                  // class com/hammajang/springbootdemo/entity/MyException11: dup                               // 复制异常对象引用12: invokespecial #6                  // Method com/hammajang/springbootdemo/entity/MyException."<init>":()V15: athrow                            // 抛出异常16: astore_1                          // 将异常对象存储在局部变量表中17: new           #7                  // class java/lang/RuntimeException20: dup                               // 复制异常对象引用21: aload_1                           // 将局部变量表中的异常对象加载到操作数栈22: invokespecial #8                  // Method java/lang/RuntimeException."<init>":(Ljava/lang/Throwable;)V25: athrow                            // 抛出异常26: astore_2                          // 将异常对象存储在局部变量表中27: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;30: ldc           #9                  // String TestMyException finally code...32: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V35: aload_2                            36: athrowException table:from    to  target type8    16    16   Class com/hammajang/springbootdemo/entity/MyException8    27    26   any

        Exception table加了finally块后,异常表中多了一条记录,表示从指令8-指令27(try块、catch块)如果抛出了任意类型(any)的异常,都会跳转到指令26(finally块)继续执行。

finally块解析:

        (1)模拟空指针异常

        JavaCodes

public class TestMyException{public static void main(String[] args) {MyException exception = null;try{exception.test();}catch (Exception e){System.out.println(e);}finally {exception = new MyException();}}
}
class MyException extends Exception{public void test(){System.out.println("test method");}
}

        ByteCodes

    Code:stack=2, locals=4, args_size=10: aconst_null1: astore_12: aload_13: invokevirtual #2                  // Method com/hammajang/springbootdemo/entity/MyException.test:()V6: new           #3                  // class com/hammajang/springbootdemo/entity/MyException9: dup10: invokespecial #4                  // Method com/hammajang/springbootdemo/entity/MyException."<init>":()V13: astore_114: goto          4717: astore_218: getstatic     #6                  // Field java/lang/System.out:Ljava/io/PrintStream;21: aload_222: invokevirtual #7                  // Method java/io/PrintStream.println:(Ljava/lang/Object;)V25: new           #3                  // class com/hammajang/springbootdemo/entity/MyException28: dup29: invokespecial #4                  // Method com/hammajang/springbootdemo/entity/MyException."<init>":()V32: astore_133: goto          4736: astore_337: new           #3                  // class com/hammajang/springbootdemo/entity/MyException40: dup41: invokespecial #4                  // Method com/hammajang/springbootdemo/entity/MyException."<init>":()V44: astore_145: aload_346: athrow47: returnException table:from    to  target type2     6    17   Class java/lang/Exception2     6    36   any17    25    36   any

有三处地方的指令需要我们注意

        1、指令6、指令9、指令10(try

        2、指令25、指令28、指令29(catch

        3、指令37、指令40、指令41(finally

        这三处地方的指令都执行同一个操作:创建并初始化MyException对象

        从字节码层面我们就可以得知为什么finally块的代码一定会执行了,因为在将.java文件编译成.class字节码文件时,编译器会将finally块的代码放在try块、catch块的末尾

        在Exception table中我们也可以看到,在指令2-指令6(try块)、指令17-25(catch块)执行时,如果抛出了任意(any)类型的异常,就会跳转到指令36(finally块)继续执行。

        

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/209551.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

msvcp100.dll丢失的常见原因/msvcp100.dll丢失的解决方法分享

在计算机使用过程中&#xff0c;我们经常会遇到一些错误提示&#xff0c;其中之一就是“msvcp100.dll丢失”。这个错误提示通常出现在运行某些程序或游戏时&#xff0c;给使用者带来了很大的困扰。那么&#xff0c;究竟是什么原因导致了msvcp100.dll文件的丢失呢&#xff1f;本…

STM32F1之CAN介绍

目录 ​编辑 1. CAN 是什么&#xff1f; 2. 总线拓扑图 3. CAN 的特点 4. CAN 协议的基本概念 1. CAN 是什么&#xff1f; CAN 是 Controller Area Network 的缩写&#xff08;以下称为 CAN&#xff09;&#xff0c;是 ISO*1 国际标准化的串行通信协议。 在当前的汽车产…

javaWebssh学生系统myeclipse开发mysql数据库MVC模式java编程计算机网页设计

一、源码特点 java ssh学生管理系统是一套完善的web设计系统&#xff08;系统采用ssh框架进行设计开发&#xff09;&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模 式开发。开发环境为TOMCAT7.0,My…

python:mplfinance 画K线图+布林线

pip install mplfinance ; python 安装使用 TA-lib 安装主要在 http://www.lfd.uci.edu/~gohlke/pythonlibs/ 这个网站找到 TA_Lib-0.4.24-cp310-cp310-win_amd64.whl pip install /pypi/TA_Lib-0.4.24-cp310-cp310-win_amd64.whl 编写 mpf_kline_boll.py 如下 # -*- cod…

【VRTK】【VR开发】【Unity】12-占位身体

课程配套学习资源下载 https://download.csdn.net/download/weixin_41697242/88485426?spm=1001.2014.3001.5503 【概要】 目前你会发现,就算存在非Trigger Collider的墙壁屏障等,也能够正常穿过,这会导致不沉浸的体验。你需要一个占位身体来实现让墙壁等碰撞并挡住自己…

`Numpy`数组中 数据的修改(第10讲)

Numpy数组中 数据的修改(第10讲)         🍹博主 侯小啾 感谢您的支持与信赖。☀️ 🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ…

YOLOv5独家原创改进:SPPF自研创新 | 可变形大核注意力(D-LKA Attention),大卷积核提升不同特征感受野的注意力机制

💡💡💡本文自研创新改进: 可变形大核注意力(D-LKA Attention)高效结合SPPF进行二次创新,大卷积核提升不同特征感受野的注意力机制。 收录 YOLOv5原创自研 https://blog.csdn.net/m0_63774211/category_12511931.html 💡💡💡全网独家首发创新(原创),适合p…

Python学习路线 - Python语言基础入门 - 函数使用

Python学习路线 - Python语言基础入门 - 函数使用 函数介绍函数函数的快速体验 函数的定义函数的定义 函数的参数函数的传入参数函数的传入参数 - 传参定义函数的传入参数 - 语法解析练习案例&#xff1a;升级版自动查询核酸 函数的返回值函数返回值的定义返回值的语法None类型…

vue中el-upload结合vuedraggable实现图片的上传、排序、删除以及预览等功能

实现效果&#xff1a; 功能实现&#xff1a; 要实现图片的拖拽功能首先需要安装vuedraggable库 npm install vuedraggable --save在组件中引入并注册 vuedraggable <script>import draggable from "vuedraggable";export default {// 注册组件components: {…

SI24R03 高度集成低功耗SOC 2.4G 收发一体芯片

今天给大家介绍一款Soc 2.4G 收发一体模块-SI24R03 Si24R03是一款高度集成的低功耗无线SOC芯片&#xff0c;芯片为QFN32 5x5mm封装&#xff0c;集成了资源丰富的MCU内核与2.4G收发器模块&#xff0c;最低功耗可达1.6uA&#xff0c;极少外围器件&#xff0c;大幅降低系统应用成本…

详解Android单元测试最佳实践

目的 充分的单元测试就是提高代码质量最有效的手段之一&#xff0c;而单元测试严重依赖代码的可测试性&#xff0c;本文主要通过一个简单的DEMO演示如何对Android原生应用进行单元测试&#xff0c;同时示例代码采用MVP模式以提高代码的可读性和可测试性 简介 在Android原生应…

mmdetection测试保存到新的文件夹,无需标签

这个是用demo这个代码测试的&#xff0c;需要先训练一个pth文件夹&#xff0c;训练之后再调用pth文件夹进行测试。测试的代码文件名是&#xff1a;image_demo_new.py&#xff0c;代码如系所示&#xff1a; # Copyright (c) OpenMMLab. All rights reserved. import asyncio fr…

使用selenium的edge浏览器登录某为

互联网上基本都是某哥的用法&#xff0c;其实edge和某哥的用法是一样的就有一下参数不一样。 一、运行环境 Python&#xff1a;3.7 Selenium&#xff1a;4.11.2 Edge&#xff1a;版本 120.0.2210.61 (正式版本) (64 位) 二、执行代码 from time import sleepfrom selenium…

调新浪分享

前端写一个按钮,通过按钮来调出新浪界面, window.location.href http://service.weibo.com/share/share.php?url 这行代码调出新浪分享界面,要是想要添加一些图片和文字 使用: window.location.href http://service.weibo.com/share/share.php?url encodeURIComponent…

P2 Qt Creator创建第一个Qt程序

前言 &#x1f3ac; 个人主页&#xff1a;ChenPi &#x1f43b;推荐专栏1: 《C_ChenPi的博客-CSDN博客》✨✨✨ &#x1f525; 推荐专栏2: 《LLinux C应用编程&#xff08;概念类&#xff09;_ChenPi的博客-CSDN博客》✨✨✨ &#x1f33a;本篇简介 &#xff1a;这一章我们学…

二百一十一、Flume——Flume实时采集Linux中的Hive日志写入到HDFS中(亲测、附截图)

一、目的 为了实现用Flume实时采集Hive的操作日志到HDFS中&#xff0c;于是进行了一场实验 二、前期准备 &#xff08;一&#xff09;安装好Hadoop、Hive、Flume等工具 &#xff08;二&#xff09;查看Hive的日志在Linux系统中的文件路径 [roothurys23 conf]# find / -name…

smarty模版 [BJDCTF2020]The mystery of ip 1

打开题目 点击flag给了我们一个ip 点击hint&#xff0c;查看源代码处告诉了我们要利用这个ip bp抓包&#xff0c;并添加X-Forward-For头 所以这道题是XFF可控 本来联想到XFF漏洞引起的sql注入&#xff0c;但是我们无论输入什么都会正常回显&#xff0c;就联想到ssti注入 我们…

CloudCompare 二次开发(23)——计算两点云之间的放缩倍数

目录 一、概述二、代码集成三、结果展示一、概述 使用CloudCompare编程实现计算两点云之间的放缩倍数。具体计算原理见:。 二、代码集成 1、mainwindow.h文件public中添加: void doActionComputeScale(); // 计算两点云的放缩倍数2、mainwindow.cpp文件void MainWin…

Python网络爬虫的基础理解-对应的自我理解误区

##通过一个中国大学大学排名爬虫的示例进行基础性理解 以软科中国最好大学排名为分析对象&#xff0c;基于requests库和bs4库编写爬虫程序&#xff0c;对2015年至2019年间的中国大学排名数据进行爬取&#xff1a;&#xff08;1&#xff09;按照排名先后顺序输出不同年份的前10…

Linux下通过find找文件---通过修改时间查找(-mtime)

通过man手册查找和-mtime选项相关的内容 man find | grep -A 3 mtime # 这里简单介绍了 -mtime &#xff0c;还有一个简单的示例-mtime n Files data was last modified n*24 hours ago. See the comments for -atime to understand how rounding affects the interpretati…