【JavaSE】浅谈Java异常

前言

本篇文章是对Java异常体系相关内容及部分注意事项的的讲解。

一. 认识异常

在每个人的生命历程中,或多或少都会遇到生病或受伤的情况,比如:皮肤擦伤、感冒、发烧、患上某些传染病等等。不管“病情”严重与否,这些都可以算作人体出现的“异常”。

在Java中,一个程序执行过程中发生的不正常行为就称为异常

在Java的异常体系中,可以分为 Exception(异常) 和 Error(错误)两大类, 它们都继承自 Throwable 这个顶级父类,而 Exception 又可以分为 Checked Exception(受查异常) 和 Unchecked Exception(非受查异常)两大类,每一类异常又划分出各类详细的异常。(如下图)
在这里插入图片描述

在上图异常体系中:

  • Error 指的是 JVM 无法解决的严重问题,它通常由环境问题或严重的系统错误引起。这种错误通常不建议进行捕获
  • Exception 指的是程序本身可以处理的异常,通常可以使用 try-catch 的方式对异常进行捕获,并在发生时针对具体的异常做出不同的处理。
  • 其中Exception 的子类 Checked Exception(受查异常,也称作编译时异常)必须在编译期间进行处理(try-catch 或 将异常作为声明抛出);Unchecked Exception (非受查异常,也称作运行时异常)通过在程序运行期间才会被发现,因此则无需进行显式处理,在异常真正发生时会交给 JVM 处理。(如下图)

在这里插入图片描述

在这里插入图片描述


二. 异常的处理

1. 异常处理的两种思维方式

首先,我们必要要清楚一个事实:对于编程初学者或经验不足的编程人员来说,写出有 BUG(异常)的程序是一个正常的现象,我们不能因此害怕异常,而应该在每次异常出现时了解异常出现在代码层面的根本原因,学习与积累解决异常的方法。这样长久以往,我们终能写出一个 BUG 很少的程序。(甚至没有 BUG。当然了,这只是对自己的激励,现实情况中再牛的程序也会出现 BUG)

咳咳,回到正文。

对于不可预期的异常,通常有两种解决的思维方式:(1)“防御式” 编程(2)“事后认错型”编程。

  • “防御式”编程:在一个完整的事件流程中,针对每一步骤的执行结果进行检查,若其中某个步骤的执行结果出现错误则立即终止执行流程,以免后续得到不可预期的错误结果。(如下图)
    在这里插入图片描述
    从上图可以发现:“防御式”编程会严格检查每一步的执行结果,确保错误在第一时间被发现并处理。但上述伪代码的执行流程存在一个明显的问题:正常的执行流程和错误处理流程混合在一起,导致代码的简洁性和可读性比较差

  • “事后认错型”编程:让可能出现异常的流程先执行,等到异常真正出现再统一对异常进行处理。(推荐!)
    在这里插入图片描述
    从上图不难发现:正常流程和错误处理流程分开,可以让程序员清晰直观地了解执行流程,增强代码的可读性。

2. 处理异常

在Java中,对异常的处理主要涉及到 5 个关键字:throwthrowstrycatchfinally

  1. throw:该关键字用于在代码中主动抛出一个指定的异常。这个异常需要是 Throwable 类或其子类的实例。它的作用是在程序出现错误时,将对应的错误信息通知给调用者。

它的使用示例如下:

	// 该方法的作用:为数组指定下标设置 val
	public boolean setElement(int[] nums, int val, int index) {
	    if (nums == null) {
	        throw new NullPointerException();
	    }
	
	    if (index < 0 || index >= nums.length) {
	        throw new IndexOutOfBoundsException();
	    }
	
	    nums[index] = val;
	    return true;
	}
  1. throws:该关键字用于方法声明时提示该方法可能会抛出的异常类型。调用方必须对这些可能抛出的异常进行处理,若调用方不想对异常做出处理,依然可以使用 throws 关键字抛出这些异常,将异常处理交给上一层的调用者, throws 最多能将处理权传递到 main()方法,即交给 JVM 处理。

它的使用示例如下:

	public static void readFile() throws IOException{
	    // 对一个文件的内容进行读取
	}
	
	public static void databaseOption() throws SQLException {
	    // 查询或修改数据库数据
	}

注意:
throws用于声明可能抛出的受查异常。因为对于非受查异常来说,只有在程序运行期间才会被发现,因此即使一个自定义方法在方法签名中声明了非受查异常,方法的调用方也不需要对该异常进行显式处理

  1. try:该关键字用于定义一个代码块,其中包含可能抛出异常的语句。try 关键字用于处理受查异常时不能单独使用,后面通常需要跟着多个 catch 块或一个 finally 块。(catch 和 finally 至少需要一个,也可以同时使用)
  2. catch:该关键字定义的代码块用于处理捕获到的异常。
  3. finally:无论 try代码块 中是否抛出异常,finally 关键字定义的代码块最终都会执行,它主要用于释放被打开的资源,防止发生异常时后续关闭资源的语句不能被及时调用,从而造成系统资源泄露的问题。例如: IO读写流、数据库连接等。

它的使用示例如下:

    public static void main(String[] args) {

        try {
            readFile();
            databaseOption();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            // 进行收尾工作及释放已打开的资源
        }

    }


    public static void readFile() throws IOException {
        // 对一个文件的内容进行读取
    }

    public static void databaseOption() throws SQLException {
        // 查询或修改数据库数据
    }

运行结果如下:

注意:finally中的代码块不一定会执行。这与上面 finally 关键字的说明并不冲突,比如以下三种特殊情况:
(1)在 finally 代码块执行前,Java虚拟机被提前终止运行(如下图)(2)程序所在的线程死亡(3)CPU被关闭

在这里插入图片描述


三. 使用 try-resource-with 代替 try-catch-finally

try-resource-with 是 Java7 引入的一种异常处理机制,用于自动关闭资源。它的使用初心与 try-catch-finally 一致,都是为了在程序发生异常时及时关闭已打开的资源,但使用 try-resource-with可以使写出的代码更加简洁清晰,并且能够有效减少因忘记关闭资源导致的系统资源泄露问题。

try-resource-with 的适用范围(资源的定义):任何实现 java.lang.AutoCloseablejava.io.Closeable 的对象。
try-resource-with 的执行顺序:无论是否发生异常,都会在 try 代码块执行结束后自动调用关闭资源的操作。

它的使用示例如下:

	public static void main(String[] args) {
		// 使用 try 将要打开的资源用括号“包裹”起来
        try (FileReader reader = new FileReader("test.txt")) {
            // 执行文件读写操作
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

注意:try 关键字后的括号可以包含多个需要使用的资源,它们之间使用 ; 进行分隔。(如下)

	public static void main(String[] args) {
        try (FileReader reader = new FileReader("test.txt");
            FileWriter writer = new FileWriter("text2.txt")) {
            // 执行文件读写操作
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

以上就是本篇文章的全部内容了,如果这篇文章对你有些许帮助,你的点赞、收藏和评论就是对我最大的支持。
另外,文章可能存在许多不足之处,也希望你可以给我一点小小的建议,我会努力检查并改进。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

数据链路层协议——以太网协议

目录 要解决的问题 以太网协议 以太网帧格式 MAC地址 MAC地址和IP地址 MTU MTU对IP协议的影响 MTU对UDP协议的影响 MTU对TCP协议的影响 ARP协议 ARP协议格式 ARP协议的工作流程 ARP缓存表 要解决的问题 上一篇我们也说了&#xff0c;数据从应用层一步步封装到了网…

leetcode:滑动窗口----3. 无重复字符的最长子串

给定一个字符串 s &#xff0c;请你找出其中不含有重复字符的 最长 子串 的长度。 示例 1: 输入: s "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "abc"&#xff0c;所以其长度为 3。示例 2: 输入: s "bbbbb" 输出: 1 解释: 因为…

工业现场ModbusTCP转EtherNETIP网关引领生物现场领新浪潮

生物质发生器是一种能够产生、培养生物的设备。客户现场需要将生物发生器连接到罗克韦尔系统&#xff0c;但是二者协议无法直接通讯&#xff0c;需要通过开疆智能ModbusTCP转Ethernet/IP网关将两者进行通讯连接&#xff0c;生物质发生器以其独特的工作原理和优势&#xff0c;使…

【命名空间详解】c++入门

目录 命名空间的定义 1.命名空间的正常定义 2.命名空间还可以嵌套 3. 命名空间可以合并 命名空间的使用 1.加命名空间名称及作用域限定符 2.使用using将命名空间中某个成员引入 3.使用using namespace 命名空间名称 引入 输入&#xff0c;输出 输出 命名空间的定义 …

[阅读笔记21][RA-CM3]Retrieval-Augmented Multimodal Language Modeling

这篇论文是meta联合斯坦福在23年4月发表的论文&#xff0c;提出了一个使用外部知识检索增强的多模态模型。 这篇模型提出的RA-CM3模型是第一个能够检索并生成图像文本的多模态模型&#xff0c;在图像文本生成任务上优于现有的多模态模型&#xff0c;同时使用更少的训练量。 RA-…

在PostgreSQL中如何处理大对象(Large Objects),例如存储和检索二进制文件?

文章目录 存储二进制文件为大对象步骤 1&#xff1a;创建一个大对象步骤 2&#xff1a;写入数据到大对象 检索大对象为二进制文件步骤 1&#xff1a;打开大对象以进行读取步骤 2&#xff1a;从大对象读取数据 注意事项 PostgreSQL 提供了对大对象&#xff08;Large Objects&…

【多线程学习】深入探究阻塞队列与生产者消费者模型和线程池常见面试题

˃͈꒵˂͈꒱ write in front ꒰˃͈꒵˂͈꒱ ʕ̯•͡˔•̯᷅ʔ大家好&#xff0c;我是xiaoxie.希望你看完之后,有不足之处请多多谅解&#xff0c;让我们一起共同进步૮₍❀ᴗ͈ . ᴗ͈ აxiaoxieʕ̯•͡˔•̯᷅ʔ—CSDN博客 本文由xiaoxieʕ̯•͡˔•̯᷅ʔ 原创 CSDN 如…

【vue】el-tree的新增/编辑/删除节点

1、概述 关于树形结构的新增同级节点&#xff0c;新增子级节点&#xff0c;修改节点名称&#xff0c;删除节点等四种操作&#xff0c;各种参数配置完全继承el-tree&#xff0c;本篇使用vue2 element-ui 2、效果图展示 3、调用方式 <template><Tree:data"tree…

上位机图像处理和嵌入式模块部署(树莓派4b和视觉slam十四讲)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 实际使用中&#xff0c;树莓派4b是非常好的一个基础平台。本身板子价格也不是很贵&#xff0c;建议大家多多使用。之前关于vslam&#xff0c;也就是…

CSS display属性

目录 概述&#xff1a; 设置display示例&#xff1a; none&#xff1a; block&#xff1a; inline&#xff1a; inline-block &#xff1a; 概述&#xff1a; 在CSS中我们可以使用display属性来控制元素的布局&#xff0c;我们可以通过display来设置元素的类型。 在不设置…

webpack源码分析——enhanced-resolve库之getType、normalize、join和cachedJoin函数

一、PathType 路径类型 const PathType Object.freeze({Empty: 0, // 空Normal: 1, // 默认值Relative: 2, // 相对路径AbsoluteWin: 3, // win 下的绝对路径AbsolutePosix: 4, // posix 下的绝对路径Internal: 5 // enhanced-resolve 内部自定义的一种类型&#xff0c;具体是…

Redis:报错Creating Server TCP listening socket *:6379: bind: No error

错误&#xff1a; window下启动redis服务报错&#xff1a; Creating Server TCP listening socket *:6379: bind: No error 原因&#xff1a; 端口6379已被绑定&#xff0c;应该是因为上次未关闭服务 解决&#xff1a; ①依次输入命令&#xff1a; redis-cli.exe &#xff08…

IntelliJ IDEA运行发布传统Java Web Application项目

接 重温8年前项目部署 要求&#xff0c;如何改用IntelliJ IDEA运行发布传统 Java Web Application项目呢&#xff0c;简述步骤如下&#xff1a; 一、下载源码 源码&#xff1a;https://github.com/wysheng/kindergarten 下载后的本地项目路径&#xff1a;/Users/songjianyon…

前后端跨域请求代码实战(vue3.4+springboot2.7.18)

前端代码 v3.4.21&#xff08;前端不是主业&#xff0c;所以就贴一贴代码&#xff0c;有疑问评论区见&#xff09;后端代码&#xff0c;springboot 2.7.18&#xff08;后端&#xff09; 文章内容&#xff1a; 一&#xff0c;后端代码 二&#xff0c;前端代码 三&#xff0c;后…

安全开发实战(1)--Cdn

目录 安全开发专栏 CDN介绍 1.信息收集阶段 1.1判断CDN是否存在 1.1.1, One 1.1.2,Two(改进) 1.1.3,进行整合 增加输入功能 1.1.4 批量读取监测存储(进行测试) 问题1: 问题2: 解决方案: 1.1.4 基本编写完成 命令框中: cdn存在.txt 总结 这里我是根据整个渗透测…

个人网页地址发布页面源码

源码介绍 个人网页地址发布页面源码&#xff0c;源码由HTMLCSSJS组成&#xff0c;记事本打开源码文件可以进行内容文字之类的修改&#xff0c;双击html文件可以本地运行效果&#xff0c;也可以上传到服务器里面 效果预览 源码下载 个人网页地址发布页面源码

利用搞笑电影,引爆中年圈,日入2000+,短视频最新变现玩法,适合0基础小白

大家好&#xff0c;今天要分享的项目是“通过搞笑电影吸引中年群体&#xff0c;实现日收入2000的短视频变现新策略&#xff0c;适合零基础新手”。该项目着眼于利用搞笑电影内容来吸引中年观众&#xff0c;这是一个相对未被充分开发的市场领域&#xff0c;竞争较少。与其他热门…

香港服务器_免备案服务器有哪些正规的?企业、建站方向

香港服务器&#xff0c;是最受欢迎的外贸、企业建站服务器&#xff0c;在个人建站领域&#xff0c;香港服务器、香港虚拟主机都是首选的网站服务器托管方案&#xff0c;不仅其具备免备案的特点&#xff0c;而且国内外地区访问速度都很快。那么&#xff0c;现今2024年个人和企业…

企业监管工具:为何如此重要?

随着通信技术的发展&#xff0c;员工使用微信等即时通讯工具来进行工作沟通已经成为了常态。为了帮助企业有效地监管员工的工作微信使用情况&#xff0c;微信管理系统应运而生。 下面就一起来看看&#xff0c;它都有哪些功能吧&#xff01; 1、历史消息&#xff1a;洞察员工聊…

力扣---从前序与中序遍历序列构造二叉树

给定两个整数数组 preorder 和 inorder &#xff0c;其中 preorder 是二叉树的先序遍历&#xff0c; inorder 是同一棵树的中序遍历&#xff0c;请构造二叉树并返回其根节点。 示例 1: 输入: preorder [3,9,20,15,7], inorder [9,3,15,20,7] 输出: [3,9,20,null,null,15,7]示…