通过异常处理错误

news2024/11/30 8:48:54

写在前面

Java的基本理念是"结构不佳的代码不能运行"。

发现错误的理想时机是在编译阶段, 也就是在你试图运行程序之前。然而, 编译期间并不能找出所有的错误, 余下的问题必须在运行期间解决。这就需要错误源能通过某种方式, 把适当的信息传递给某个接收者——该接收者将知道如何正确处理这个问题。

错误恢复在我们所编写的每一个程序中都是基本的要素, 但是在Java中它显得格外重要, 因为Java的主要目标之一就是创建供他人使用的程序构件。要想创建健壮的系统, 它的每一个构件都必须是健壮的。Java使用异常来提供一致的错误报告模型, 使得构件能够与客户端代码可靠地沟通问题。

异常处理是Java中唯一正式的错误报告机制, 并且通过编译器强制执行。

概念

"异常"这个词有"我对此感到意外"的意思。问题出现了, 你也许不清楚该如何处理, 但你的确知道不应该置之不理; 你要停下来, 看看是不是有别人或在别的地方, 能够处理这个问题。只是在当前的环境中还没有足够的信息来解决这个问题, 所以就把这个问题提交到一个更高级别的环境中, 在这里将做出正确的决定。

使用异常所带来的另一个明显的好处是, 它往往能够降低错误处理代码的复杂度, 如果不适用异常, 那么就必须检查特定的错误, 并在程序的许多地方去处理它。而如果使用异常, 那就不必在方法调用处进行检查, 因为异常机制将保证能够捕获这个错误。并且, 只需在一个地方处理错误, 即所谓的异常处理程序中。这种方式不仅节省代码, 而且把"描述在正常执行过程中做什么事"的代码和"出了问题怎么办"的代码相分离。总之, 与以前的错误处理方法相比, 异常使代码的阅读、编写和调试工作更加井井有条

基本异常

普通问题是指, 在当前环境下能够得到足够的信息, 总能处理这个错误。而对于异常情形, 就不能继续下去了, 因为在当前环境下无法获得必要的信息来解决问题。你所能做的就是从当前环境跳出, 并且把问题提交给上一级环境。这就是抛出异常时所发生的事情。

当抛出异常后, 有几件事会随之发生。首先, 同Java中其他对象的创建一样, 将使用new在堆上创建异常对象。然后, 当前的执行路径被终止, 并且从当前环境中弹出对异常对象的引用。此时, 异常处理机制接管程序, 并开始寻找一个恰当的地方来继续执行程序。这个恰当的地方就是异常处理程序, 它的任务是将程序从错误状态中恢复, 以使程序能要么换一种方式运行, 要么继续运行下去。

异常最重要的方面之一就是如果发生问题, 它们将不允许程序沿着其正常的路径继续走下去。

与使用Java中的其他对象一样, 我们总是new在堆上创建异常对象, 这也伴随着存储空间的分配和构造器的调用。所有标准异常类都有两个构造器: 一个是默认构造器; 另一个是接受字符串作为参数, 以便能够把相关信息放入异常对象的构造器:

throw new NullPointerException("t = null");

捕获异常

要明白异常是如何被捕获的, 必须首先理解监控区域(guarded region)的概念。它是一段可能产生异常的代码, 并且后面跟着处理这些异常的代码。

try块

如果在方法内部(或在方法内部调用的其他方法)抛出了异常, 这个方法将在抛出异常的过程中结束。要是不希望方法就此结束, 可以在方法内设置一个特殊的块来捕获异常。因为在这个块里"尝试"各种(可能产生异常的)方法调用, 所以称为try块。它是跟在try关键字之后的普通程序块:

try{
    // Code that might generate exceptions
}

所以有了异常处理机制, 可以把所有动作都放在try块里, 然后只需在一个地方就可捕获所有异常, 这意味着代码将更容易编写和阅读, 因为完成任务的代码没有与错误检查的代码混在一起。

异常处理程序

抛出的异常必须在异常处理程序得到处理, 而且针对每个要捕获的异常, 得准备响应的处理程序。异常处理程序紧跟在try块之后, 以关键字catch表示:

try{
    // Code that might generate exceptions
}catch(Type1 id1){
    // Handle exceptions of Type1
}catch(Type2 id2){
    // Handle exceptions of Type2
}catch(Type3 id3){
    // Handle exceptions of Type3
}

异常处理程序必须紧跟在try块之后。当异常被抛出时, 异常处理机制将负责搜寻参数与异常类型相匹配的第一个处理程序。然后进入catch子句执行, 此时认为异常得到了处理。一旦catch子句结束, 则处理程序的查找过程结束。注意, 只有匹配的catch子句才能得到执行;这与switch语句不同, switch语句需要在每一个case后面跟一个break, 以避免执行后续的case子句。

try块内部, 不同的方法调用可能会产生类型相同的异常, 而你只需要提供一个针对此类型的异常处理程序

创建自定义异常

Java提供的异常体系不可能预见所有的希望加以报告的错误, 所以可以自己定义异常类来表示程序中可能会遇到的特定问题。

要自己定义异常类, 必须从已有的异常类型继承, 最好是选择意思相近的异常类继承(不过这样的异常并不容易找)。建立新的异常类型最简单的方法就是让编译器为你产生默认构造器

也可以为异常类定义一个接受字符串参数的构造器

捕获所有异常

可以只写一个异常处理程序来捕获所有类型的异常。通过捕获异常类型的基类Exception, 就可以做到这一点(事实上还有其他的基类, 但Exception是同编程活动相关的基类):

catch(Exception e){
    System.out.println("Caught an exception");
}

这将捕获所有异常, 所以最好把它放在处理程序列表的末尾, 以防它抢在其他处理程序之前先把异常捕获了

可以调用它从其基类Throwable继承的方法:

String getMessage()

String getLocalizedMessage()

用来获取详细信息, 或用本地语言表示的详细信息

void printStackTrace()

void printStackTrace(PrintStream)

void printStackTrace(java.io.PrintWriter)

Throwable fillInStackTrace()

此外, 也可以使用Throwable从其基类Object(也是所有类的基类)继承的方法, 对于异常来说, getClass()也许是一个很好用的方法, 它将返回一个表示此对象类型的对象。然后可以使用getName()方法查询这个Class对象包含包信息的名称, 或者使用只产生类名称的getSimpleName()方法。

应用

在Java语言中,异常的继承结构大致是:

如果调用的某个方法抛出了非RuntimeException,则必须在源代码中使用try...catch或throws语法,否则,源代码将报错!而RuntimeException不会受到这类语法的约束!

在项目中,如果需要通过抛出异常来表示某种“错误”,应该使用自定义的异常类型,否则,可能与框架或其它方法抛出的异常相同,在处理时,会模糊不清(不清楚异常到底是显式的抛出的,还是调用其它方法时由那些方法抛出的)!同时,为了避免抛出异常时有非常多复杂的语法约束,通常,自定义的异常都会是RuntimeException的子孙类异常。

另外,抛出异常时,应该对出现异常的原因进行描述,所以,在自定义异常类中,应该添加带String message参数的构造方法,且此构造方法需要调用父类的带String message参数的构造方法。

则在项目的根包下创建ex.ServiceException异常类,继承自RuntimeException,例如:

然后,在Service中,就抛出此类异常,并添加对于错误的描述文本,例如:

在Controller中,将调用Service中的方法,可以使用try..catch包裹这段代码,对异常进行捕获并处理,例如:

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

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

相关文章

情人节特刊 | “恋爱容易,相守难!” 犀思老兵谈破局之道!

付出甘之如饴,所得归于欢喜。 主动付出真心,问心无愧,未来无悔。老吴是我们公司十多年经验的售后服务主管,平时聊的不多,中午一起吃饭,偶然看到新闻说春节后多地都有排队办理离婚的现象。我不禁感叹一句&am…

三种查找Windows10环境变量的方法

文章目录一.在设置中查看二. 在我的电脑中查看三. 在资源管理器里查看一.在设置中查看 在系统中搜索设置 打开设置,在设置功能里,点击第一项 系统 在系统功能里,左侧菜单找到关于 在关于的相关设置里可以看到高级系统设置 点击高级系…

Java如何整合FFmpeg、FFprobe等音视频处理工具,零基础照样玩

前言:时隔一年多了,不知不觉博客停更那么久了,那不忘初心还记得吗? 最近在做音视频相关的开发,没什么资料并且之前也没有接触过这方面, 咨询了T届的好友,拿到了下面的这张表情包,问题…

从事架构师岗位快2年了,聊一聊我和ChatGPT对架构的一些感受和看法

从事架构师岗位快2年了,聊一聊我和ChatGPT对架构的一些感受和看法 职位不分高低,但求每天都能有新的进步,永远向着更高的目标前进。 文章目录踏上新的征程架构是什么?架构师到底是干什么的?你的终极目标又是什么&#…

链表带头结点与不带头节点的区别

链表是一种物理存储结构上非连续,非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的 链表可分为:单链表和双链表,带头结点的链表和不带头结点的链表,循环链表和非循环链表 为了表示每个元素与其…

MySQL数据库调优————SQL性能分析

TIPS 本文基于MySQL 8.0 本文探讨如何深入SQL内部,去分析其性能,包括了三种方式: SHOW PROFILEINFORMATION_SCHEMA.PROFILINGPERFORMANCE_SCHEMA SHOW PROFILE SHOW PROFILE是MySQL的一个性能分析命令,可以跟踪SQL各种资源消耗。…

VLAN间通信,看完这个就完全懂了(单臂路由和三层交换)

第九章:实现VLAN间通信 划分VLAN后,由于广播报文只在同VLAN内转发,所以不同VLAN的用户间不能二层互访,这样能起到隔离广播的作用。但实际应用中,不同VLAN的用户又常有互访的需求,此时就需要实现不同VLAN的…

KDNM5000-10A-2剩余电流保护器测试仪

一、产品概述 KDNM5000-10A-2型剩余电流保护器测试仪(以下简称测试仪),是本公司改进产品,是符合国家标准《剩余电流动作保护器》(GB6829—95)中第8.3条和GB16917.1—1997中第9.9条验证AC型交流脱扣器动作特性要求的专用测试仪器。…

Nacos微服务笔记

Nacos安装Nacos 的 Github(Tags alibaba/nacos GitHub)下载我们所需的 Nacos 版本,可以选择 windows 或者 Linux。 进入官网,选择合适版本,tar.gz为linux版本,zip为windows版本。下载并解压 nacos-server…

【C++进阶】一、继承(总)

目录 一、继承的概念及定义 1.1 继承概念 1.2 继承定义 1.3 继承基类成员访问方式的变化 二、基类和派生类对象赋值转换 三、继承中的作用域 四、派生类的默认成员函数 五、继承与友元 六、继承与静态成员 七、菱形继承及菱形虚拟继承 7.1 继承的分类 7.2 菱形虚拟…

【SAP Abap】X-DOC:SE11 - 创建配置表并分配事务码

SE11 - 创建配置表并分配事务码1、创建自定义表2、创建表维护功能3、功能验证4、设置事务码5、带出字段默认值(1)方法一:表维护事件(2)方法二:屏幕事件1、创建自定义表 SE11,创建自定义表&…

结构体的三种定义方法、结构体类型名(可选标志符)什么时候可以省略

结构体的三种定义方法 一、单独定义: 先定义结构体类型,再定义变量   定义结构体的格式如下:    struct 结构体名 {    若干数据项;    } ;   其中,struct为关键字; 结构体名是用户定…

golang 入门教程:迷你 Twitter 后端

请记住,这个项目主要是为了稍微熟悉下Golang,您可以复制架构,但该项目缺少适当的 ORM,没有适当的身份验证或授权,我完全无视中间件,也没有测试。 我将在其自己的部分中讨论所有这些问题,但重要的…

利用NGROK将本地网站发布为一个公开网站

一般与第三方服务集成时,需要提供https的回调URL,本地开发阶段可以利用NGROK将本地网站发布为公开的https网站。https://ngrok.com/downloadWindow下载地址:https://bin.equinox.io/c/bNyj1mQVY4c/ngrok-v3-stable-windows-amd64.zip以Window…

echarts问题汇总

因为工作中经常使用echarts,做数据可视化相关需求,需要实现各种各样图表的需求。 有遇到过很多问题,一些网上不太好搜索到解决方案的,一直想总结一下解决过程。方便自己查阅,也方便别人参考。 一:echarts…

【C++】set/multiset、map/multimap的使用

目录 一、关联式容器 二、set的介绍 1、接口count与容器multiset 2、接口lower_bound和upper_bound 三、map的介绍 1、接口insert 2、接口insert和operator[]和at 3、容器multimap 四、map和set相关OJ 1、前K个高频单词 2、两个数组的交集 一、关联式容器 vector、…

【LeetCode】环形链表 II [M](链表)

142. 环形链表 II - 力扣(LeetCode) 一、题目 给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。 如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链…

Python网络爬虫 学习笔记(1)requests库爬虫

文章目录Requests库网络爬虫requests.get()的基本使用框架requests.get()的带异常处理使用框架(重点)requests库的其他方法和HTTP协议(非重点)requests.get()的可选参数网络爬虫引发的问题(非重点)常见问题…

【C/C++】Windows下VS创建Linux项目

如果不想在Linux下用vim编写代码,可以在Windows下使用VS远程连接Linux(Linux下是不支持安装使用VS的),将VS上编写的代码通过 SSH协议 推送到Linux下,注意文件编写是在Windows上进行的,编译是在Linux下进行的…

【Hello Linux】Linux工具介绍 (make/makefile git)

作者:小萌新 专栏:Linux 作者简介:大二学生 希望能和大家一起进步! 本篇博客简介:介绍Linux的常用工具make/makefile git Linux项目自动化构建工具 – make/Makefile 背景 会不会写Makefile 从侧面说明了一个人是否具…