【Java】基础入门 (十六)--- 异常

1.异常

1.1 异常概述

       异常是指程序在运行过程中出现的非正常的情况,如用户输入错误、除数为零、文件不存在、数组下标越界等。由于异常情况再程序运行过程中是难以避免的,一个良好的应用程序除了满足基本功能要求外,还应具备预见并处理可能发生的各种异常情况。因此,在开发中需要充分考虑各种意外情况,以提高程序的容错能力。异常处理事一种技术,用于处理这种异常情况。

       我们阅读下面的代码,通过这段代码来认识异常。 我们调用一个方法时,经常一不小心就出异常了,然后在控制台打印一些异常信息。其实打印的这些异常信息,就叫做异常。

public class ExceptionTest01 {public static void main(String[] args) {System.out.println(Integer.valueOf("abc"));}
}

       运行之后会出现如下的页面:

在这里插入图片描述

       因为在设计这个方法的时候,在方法中对调用者传递的参数进行校验,如果校验数据不合法,就会将异常信息封装成一个对象并抛出,JVM接收到异常对象之后,就把异常打印了。

public static Integer valueOf(String s) throws NumberFormatException {return Integer.valueOf(parseInt(s, 10));
}

       因为写代码时经常会出现问题,Java的设计者们早就为我们写好了很多个异常类,来描述不同场景下的问题。而有些类是有共性的所以就有了异常的继承体系。

1.1.1 异常的体系

在这里插入图片描述

所有异常类都是Throwable类的子类,它派生出两个子类, Error 类和 Exception 类:

       (1) Error 类:表示程序无法恢复的严重错误或者恢复起来比较麻烦的错误,例如内存溢出、动态链接失败、虚拟机错误等。应用程序不应该主动抛出这种类型的错误,通常由虚拟机自动抛出。如果出现这种错误,最好的处理方式是让程序安全退出。在进行程序设计时,我们更应关注Exception类。
       (2)Exception类:由Java应用程序抛出和处理的非严重错误,例如文件未找到、网络连接问题、算术错误(如除以零)、数组越界、加载不存在的类、对空对象进行操作、类型转换异常等。Exception类的不同子类对应不同类型的异常。Exception类又可分为两大类异常:

  • 不受检异常:也称为unchecked异常,包括RuntimeException及其所有子类。对这类异常并不要求强制进行处理,例如算术异常ArithmeticException等。
  • 受检异常:也称为checked异常,指除了不受检异常外,其他继承自Exception类的异常。对这类异常要求在代码中进行显式处理。

Java提供了多种异常类,下表列举了一些常见的异常类及其用途:

在这里插入图片描述

1.2 Java异常处理机制

1.2.1 异常处理

       Java的异常处理机制类似于人们对可能发生的意外情况进行预先处理的方式。在程序执行过程中,如果发生了异常,程序会按照预定的处理方式对异常进行处理。处理完异常之后,程序会继续执行。如果异常没有被处理,程序将会终止运行。

       Java的异常处理机制依靠以下 5 个关键字:trycatchfinallythrowthrows。这些关键字提供了两种异常处理方式。

(1)使用try、catch、finally来捕获和处理异常:

  • try 块中包含可能会抛出异常的代码。
  • catch 块中用于捕获并处理指定类型的异常。
  • finally 块中的代码无论是否发生异常都会被执行,通常用于释放资源或清理操作。
package swp.kaifamiao.codes.Java.d0830;/*** {class description}** @author SWP* @version 1.0.0*/
public class Main {public static void main(String[] args) {try {int i = 1, j = 0, res;System.out.println("begin");res = i / j;System.out.println("end");}catch (ArithmeticException e){System.out.println("caught");e.printStackTrace();}finally {System.out.println("finally");}System.out.println("over");}
}

运行效果:

在这里插入图片描述

(2)使用throw、throws 来抛出异常:

       ① 使用throws声明抛出异常

       try-catch-finally 处理的是在方法内部发生的异常,在方法内部直接捕获并处理。如果在一个方法体内抛出了异常,并希望调用者能够及时地捕获异常,Java语言中通过关键字throws声明某个方法可能抛出的各种异常,以通知调用者。throws 可以同时声明多个异常,之间用逗号隔开。

package swp.kaifamiao.codes.Java.d0830;import java.util.InputMismatchException;
import java.util.Scanner;/*** {class description}** @author SWP* @version 1.0.0*/
public class Demo01 {public static void main(String[] args) {try {divide();}catch (InputMismatchException e){System.out.println("除数和被除数必须都是整数");}catch (ArithmeticException e){System.out.println("除数不能为零");}catch (Exception e){System.out.println("其他异常" + e.getMessage());}finally {System.out.println("感谢使用本程序");}System.out.println("程序结束");}/**通过throws声明抛出设计时异常*/public static void divide() throws Exception{Scanner input = new Scanner(System.in);System.out.println("计算开始");int i, j, res;System.out.println("请输入被除数");i = input.nextInt();System.out.println("请输入除数");j = input.nextInt();res = i / j;System.out.println(i + "/" + j + "=" + res);System.out.println("计算结束");}
}

       ②使用throw声明抛出异常

       除了系统自动抛出异常外,在编程过程中,有些问题是系统无法自动发现并解决的,如年龄不在正常范围之内,性别输入的不是“男”或“女”等,此时需要程序员而不是系统来自行抛出异常,把问题提交给调用者去解决。在Java语言中,可以使用throw关键字来自行抛出异常。

throw new Exception("message")
  • 如果 throw 语句抛出的异常是 Checked 异常,则该 throw 语句要么处于 try 块⾥,显式捕获该异常,要么放在⼀个带 throws 声明抛出的⽅法中,即把该异常交给该⽅法的调⽤者处理;
  • 如果 throw 语句抛出的异常是 Runtime 异常,则该语句⽆须放在 try 块⾥,也⽆须放在带 throws 声明抛出的⽅法中;程序既可以显式使⽤ try…catch来捕获并处理该异常,也可以完全不理会该异常,把该异常交给该⽅法调⽤者处理。

自行抛出Runtime 异常比自行抛出Checked 异常的灵活性更好。同样,抛出 Checked 异常则可以让编译器提醒程序员必须处理该异常。

1.2.2 自定义异常

       当JDK中的异常类型不能满足程序需求时,可以自定义异常类,使用自定义异常类一般有以下几个步骤:
       (1)定义异常类,并继承ExceptionRuntimeException
       (2)编写异常类的构造方法,向父类构造方法传入异常描述信息,并继承父类的其他实现方法;
       (3)实例化自定义异常对象,并在程序中使用throw抛出。

举例:实现以下需求

需求:写一个saveAge(int age)方法,在方法中对参数age进行判断,如果age<0或者>=150就认为年龄不
合法,如果年龄不合法,就给调用者抛出一个年龄非法异常。

分析:Java的API中是没有年龄非常这个异常的,所以我们可以自定义一个异常类,用来表示年龄非法异常,然后再方法中抛出自定义异常即可。


自定义一个AgeIllegalException异常类:

package swp.kaifamiao.codes.Java.d0830;/*** {class description}* 自定义异常类 AgeIllegalException* 继承 Exception 类* 用于表示年龄不合法的异常* @author SWP* @version 1.0.0*/
public class AgeIllegalException extends Exception {public AgeIllegalException() {}public AgeIllegalException(String message) {super(message);}
}
package swp.kaifamiao.codes.Java.d0830;/*** {class description}* 异常测试类 ExceptionTest* 用于测试自定义异常 AgeIllegalException* 当年龄不合法时抛出 AgeIllegalException 异常* 并在 main 方法中捕获并处理该异常* @author SWP* @version 1.0.0*/
public class ExceptionTest {public static void main(String[] args) {try {saveAge(225);System.out.println("saveAge2底层执行是成功的!");} catch (AgeIllegalException e) {e.printStackTrace();System.out.println("saveAge2底层执行是出现bug的!");}}// 在方法中对age进行判断,不合法则抛出AgeIllegalExceptionpublic static void saveAge(int age) throws AgeIllegalException {if (age > 0 && age < 150) {System.out.println("年龄被成功保存: " + age);} else {// 用一个异常对象封装这个问题// throw 抛出去这个异常对象throw new AgeIllegalException("age is illegal, your age is " + age);}}
}

运行效果:

在这里插入图片描述


1.2.3 异常链

异常链(Exception Chaining)是指在异常处理过程中,将当前的异常作为原因(cause)链接到另一个异常上。通过异常链,可以追踪异常发生的完整路径,并提供更多的上下文信息。

(1)定义testOne,testTwo,testThree方法,testTwo对testOne抛出的异常进行捕获,testThree对testTwo抛出的异常进行捕获:

package swp.kaifamiao.codes.Java.d0830;/*** {class description}** @author SWP* @version 1.0.0*/
public class TryDemoFive {public static void main(String[] args) {try {testThree();} catch (Exception e) {// 打印完整的异常信息e.printStackTrace();}}public static void testOne() throws MyException {throw new MyException("我是一个异常");}public static void testTwo() throws Exception {try {testOne();} catch (Exception e) {// 在新抛出的异常中添加原来的异常信息throw new Exception("我是新产生的异常1", e);}}public static void testThree() throws Exception {try {testTwo();} catch (Exception e) {// 在要抛出的对象中使用 initCause() 方法,添加上一个产生异常的信息Exception e2 = new Exception("我是新产生的异常2");e2.initCause(e);throw e2;}}
}

(2)定义MyException 类:

package swp.kaifamiao.codes.Java.d0830;/*** {class description}** @author SWP* @version 1.0.0*/
public class MyException extends Exception{public MyException(String message) {super(message);}
}

(3)运行效果:

在这里插入图片描述

2.思考

2.1 什么是异常?

	异常是指程序在运行过程中出现的非正常的情况,如用户输入错误、除数为零、文件不存在、数组下标越界等。

2.2 什么是运行时异常?

运行时异常(Runtime Exception)是指在程序运行期间可能抛出的异常,它们属于非受检异常(Unchecked Exception)。与受检异常(Checked Exception)相比,运行时异常在编译期不需要强制处理或声明。运行时异常通常表示程序的逻辑错误或者错误的使用方式,例如数组越界、空指针引用等。这些异常通常是由程序员编码时的错误导致的,但在编译时却无法确定是否会发生异常。

2.3 如何处理异常?

(1) 使用try、catch、finally来捕获和处理异常;
(2) 使用throw、throws 来抛出异常

2.4 什么是checked异常?什么是unchecked异常?

(1) 受检异常是在编译时强制要求处理的异常,需要使用 try-catch 块捕获并处理,或者在方法签名中使用 throws 关键字声明异常。
(2) 非受检异常是由程序逻辑错误或错误的使用方式引起的异常,在编译时不需要强制要求处理,但仍可以选择性地进行捕获和处理。

2.5 构造方法可以throws异常吗?对子类有影响吗?有什么影响?

可以在构造方法中抛出异常,与其他方法一样,构造方法也可以声明受检异常并通过 throws 关键字将其抛出。
如果在父类的构造方法中声明了受检异常,那么所有继承自该类的子类构造方法必须显示地处理这些异常或者在它们的方法签名中使用 throws 关键字将其抛出。否则编译会报错。

2.6 throw和throws的区别?

(1) 作⽤不同:throw⽤于程序员⾃⾏产⽣并抛出异常,throws⽤于声明该⽅法内抛出了异常。
(2) 使⽤位置不同:throw位于⽅法体内部,可以作为单独的语句使⽤;throws必须跟在⽅法参数列表的后⾯,不能单独使⽤。
(3) 内容不同:throw抛出⼀个异常对象,只能是⼀个;throws后⾯跟异常类,可以跟多个。

2.7 能否自己throw一个Error?

可以使用 throw 关键字抛出一个 Error 对象。在Java中,Error 是 Throwable 类的子类,它表示严重的错误和异常情况,通常由Java虚拟机(JVM)或底层系统引起,例如 OutOfMemoryError、StackOverflowError 等。与 Exception 不同,Error 通常表示不可恢复的错误或系统级故障,它们是无法预料和处理的,一般不建议程序员捕获和处理 Error。通常情况下,Error 会导致程序中止执行。

以下是一个示例,演示如何抛出一个 Error:

public class Example {public static void main(String[] args) {throw new Error("This is an error.");}
}

需要注意的是,抛出 Error 可能会导致程序异常终止,并且不应该被常规的异常处理机制所捕获和处理。因此,在编写代码时,通常不建议自己抛出 Error,除非确实具有特殊的需求或深入了解它们的影响。一般的异常处理应该针对 Exception 及其子类。

2.8 假如throw里面有return语句,catch里面有return语句,finally里面也有return语句,为什么最后返回的是finally里面的return语句?

在 Java 中,finally 块中的 return 语句会覆盖之前的 try 或 catch 块中的 return 语句,并决定最终的返回值。这是因为无论在 try、catch 或者 finally 块中执行了哪个 return 语句,都会直接结束整个方法并返回对应的值。根据 Java 语言规范,finally 块中的 return 语句会在方法返回之前执行,以确保在方法返回之前可以进行一些必要的清理工作。所以,在 finally 块中使用 return 语句将决定最终的返回值。

2.9 为啥要自定义异常?如何自定义异常?

当JDK中的异常类型不能满足程序需求时,可以自定义异常类,自定义异常在编程中非常有用,它能够提供更加准确和具体的异常信息,并能够满足特定业务需求。通过自定义异常,可以将代码中可能发生的异常情况进行分类和处理,使代码更加清晰、可读性更高,并且有助于调试和错误处理。
(1)定义异常类,并继承`Exception` 或`RuntimeException`;
(2)编写异常类的构造方法,向父类构造方法传入异常描述信息,并继承父类的其他实现方法;
(3)实例化自定义异常对象,并在程序中使用throw抛出。

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

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

相关文章

Linux服务器安装部署MongoDB数据库 – 【无公网IP远程连接】

文章目录 前言1.配置Mongodb源2.安装MongoDB数据库3.局域网连接测试4.安装cpolar内网穿透5.配置公网访问地址6.公网远程连接7.固定连接公网地址8.使用固定公网地址连接 前言 MongoDB是一个基于分布式文件存储的数据库。由 C 语言编写&#xff0c;旨在为 WEB 应用提供可扩展的高…

LeetCode-160. 相交链表

这是一道真的非常巧妙的题&#xff0c;题解思路如下&#xff1a; 如果让他们尾端队齐&#xff0c;那么从后面遍历就会很快找到第一个相交的点。但是逆序很麻烦。 于是有一个巧妙的思路诞生了&#xff0c;如果让短的先走完自己的再走长的&#xff0c;长的走完走短的&#xff0c;…

lib61850 学习笔记一 (概念)

IEC61850 定义60多种服务满足变电站通信需求。支持在线获取数据模型&#xff0c;也支持IED水平通信&#xff08;GOOSE报文&#xff09; 术语定义 间隔 bay: 变电站由据应公共功能紧密连接的子部分组成。 例如 介于进线或者 出线 和母线之间的断路器&#xff1b;二条母线之间…

mq与mqtt的关系

文章目录 mqtt 与 mq的区别mqtt 与 mq的详细区别传统消息队列RocketMQ和微消息队列MQTT对比&#xff1a;MQ与RPC的区别 mqtt 与 mq的区别 mqtt&#xff1a;一种通信协议&#xff0c;规范 MQ&#xff1a;一种通信通道&#xff08;方式&#xff09;&#xff0c;也叫消息队列 MQ…

深入解析SNMP协议及其在网络设备管理中的应用

SNMP&#xff08;Simple Network Management Protocol&#xff0c;简单网络管理协议&#xff09;作为一种用于网络设备管理的协议&#xff0c;在实现网络设备的监控、配置和故障排除方面发挥着重要的作用。本文将深入解析SNMP协议的工作原理、重要概念和功能&#xff0c;并探讨…

uniapp实现:点击拨打电话,弹出电话号码列表,可以选择其中一个进行拨打

一、实现效果&#xff1a; 二、代码实现&#xff1a; 在uni-app中&#xff0c;使用uni.showActionSheet方法实现点击拨打电话的功能&#xff0c;并弹出相关的电话列表供用户选择。 当用户选择了其中一个电话后&#xff0c;会触发success回调函数&#xff0c;并通过res.tapInde…

OpenGL精简案例一

文章目录 案例一 绘制点线面定义Renderer顶点着色器片段着色器内置的特殊变量 应用场景工具ShaderHelper工具 TextResourceReader效果图如下 结论 案例一 绘制点线面 定义Renderer import android.content.Context; import android.opengl.GLES20; import android.opengl.GLSu…

Vue3.0 新特性以及使用变更总结

Vue3.0 在2020年9月正式发布了&#xff0c;也有许多小伙伴都热情的拥抱Vue3.0。去年年底我们新项目使用Vue3.0来开发&#xff0c;这篇文章就是在使用后的一个总结&#xff0c; 包含Vue3新特性的使用以及一些用法上的变更。 图片.png 为什么要升级Vue3 使用Vue2.x的小伙伴都熟悉…

Vue中如何为Echarts统计图设置数据

在前端界面接收后端数据后&#xff0c;将数据赋值给ECharts中的data时出现了&#xff0c;数据读取失败的问题&#xff08;可能是由于数据渲染的前后顺序问题&#xff09;。后通过如下方式进行了解决&#xff1a; 1、接下来将介绍UserController中的countUsers方法&#xff0c;…

vue实现富文本

效果图展示 一、安装依赖 npm install vue-quill-editor --save二、具体使用 html <template><!-- 富文本 --><quill-editorref"myQuillEditor"v-model"content":options"editorOption"blur"onEditorBlur($event)"…

【模拟】算法实战

文章目录 一、算法原理二、算法实战1. leetcode1576 替换所有的问号2. leetcode495 提莫攻击3. leetcode6 N字形变换4. leetcode38 外观数列5. leetcode1419 数青蛙 三、总结 一、算法原理 模拟就是用计算机来模拟题目中要求的操作&#xff0c;模拟题目通常具有代码量大、操作…

Docker - Docker安装MySql并启动

因为项目需要连接数据库&#xff0c;但是远程服务器上的mysql我不知道账户和密码&#xff0c;这个时候便是docker发挥作用的关键时刻了&#xff01; 目录 docker安装安装gcc卸载老docker&#xff08;如有&#xff09;安装软件包设置镜像仓库更新yum软件包索引安装docker启动doc…

2023_Spark_实验二:IDEA安装及配置

一、下载安装包 链接&#xff1a;百度网盘 请输入提取码 所在文件夹&#xff1a;大数据必备工具--》开发工具(前端后端)--》后端 下载文件名称&#xff1a;ideaIU-2019.2.3.exe &#xff08;喜欢新版本也可安装新版本&#xff0c;新旧版本会存在部分差异&#xff09; IDEA …

线性代数的学习和整理11: 子式与余子式

目录 1 原始矩阵A 2 子式&#xff08;都是行列式&#xff09; 2.1 k阶子式&#xff08;行数列数即可&#xff09; 比如1阶子式&#xff1a;因为只有1行1列 比如2阶子式&#xff1a;因为有2行2列 比如3阶子式&#xff1a;因为有3行3列 2.2 k阶主子式 {行序号数组} {列序号…

VS的调试技巧

Visual Studiohttps://visualstudio.microsoft.com/zh-hans/vs/ 目录 1、什么是调试&#xff1f; 2、debug和release 3、调试 3.1、环境 3.2、 快捷键 3.2.1、F10和F11 3.2.2、ctrlF5 3.2.3、F5与F9 3.2.3.1、条件断点 3.3、监视和内存观察 3.3.1、监视 3.3.2、内存 …

CSS中如何实现元素之间的间距(Margin)合并效果?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 外边距合并的示例&#xff1a;⭐ 如何控制外边距合并&#xff1a;⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅&#xff…

Redis 列表 | Navicat

在最近的博客 文章 中&#xff0c;我们已经了解了 Redis 的六种数据类型。其中&#xff0c;Redis 列表&#xff08;List&#xff09;包含一组字符串&#xff0c;他们按照被添加的顺序进行排序。本文将就列表数据类型进行展开介绍&#xff0c;并且重点介绍一些主要的命令来管理它…

探索Python的魔法世界,开启编程奇幻之旅!

无需魔杖&#xff0c;只需键盘&#xff0c;Python将带你进入一个充满奇幻和创造力的世界。本篇博客将引领你走进Python的魔法大门&#xff0c;从编程新手蜕变为编码魔法师&#xff0c;开启一段激动人心的编程奇幻之旅。 &#x1f340;引言 如果你是一名编程初学者&#xff0c;并…

精准运营,智能决策!解锁天翼物联水利水务感知云

面向智慧水利/水务数字化转型需求&#xff0c;天翼物联基于感知云平台创新能力&#xff0c;提供涵盖水利水务泛协议接入、感知云水利/水务平台、水利/水务感知数据治理、数据看板在内的水利水务感知云服务&#xff0c;构建水利水务感知神经系统新型数字化底座&#xff0c;实现智…

【ArcGIS Pro二次开发】(63):批量更改字段别名

在我工作中遇到的大多数图斑&#xff0c;字段名称一般是英文&#xff0c;字段别名是中文&#xff0c;使用起来是比较方便的。 但有时候也会遇到一些不一样的情况&#xff0c;不知是经过了怎样的处理&#xff0c;图斑的字段别名被修改成了和字段名称一样的英文&#xff0c;这样…