认识异常 ---java

目录

一. 异常的概念

二. 异常的体系结构

三. 异常的分类

三. 异常的处理

3.1 异常的抛出throw

3.2. 异常声明throws

3.3 捕获并处理try-catch

finally

 3.4异常的处理流程

四. 自定义异常类


一. 异常的概念

Java 中,将程序执行过程中发生的不正常行为称为异常。比如之前写代码时经常遇到的:
1. 算术异常
System . out . println ( 10 / 0 );
// 执行结果
Exception in thread "main" java . lang . ArithmeticException : / by zero

2. 数组越界异常

int [] arr = { 1 , 2 , 3 };
System . out . println ( arr [ 100 ]);
// 执行结果
Exception in thread "main" java . lang . ArrayIndexOutOfBoundsException : 100

3. 空指针异常

int [] arr = null ;
System . out . println ( arr . length );
// 执行结果
Exception in thread "main" java . lang . NullPointerException

点进去任意一个异常, 我们发现:

从上述代码中可以看到,java中不同类型的异常,都有与其对应的类来进行描述 

二. 异常的体系结构

从上图中可以看到:
1. Throwable 是异常体系的顶层类,其派生出两个重要的子类 , Error Exception
2. Error 指的是 Java 虚拟机无法解决的严重问题,比如: JVM 的内部错误、资源耗尽等 ,典型代表: StackOverflowError OutOfMemoryError ,一旦发生回力乏术。
3. Exception 异常产生后程序员可以通过代码进行处理,使程序继续执行。比如:感冒、发烧。我们平时所说的异常就是Exception

三. 异常的分类

异常可能在编译时发生,也可能在程序运行时发生,根据发生的时机不同,可以将异常分为:

1. 编译时异常

在程序编译期间发生的异常,称为编译时异常,也称为受检查异常(Checked Exception)  

例: 

我们可以通俗的来理解, 在编写代码的过程中, 出现了红色的波浪线, 此时的异常就叫做编译时异常或受查异常.

2. 运行时异常

在程序执行期间发生的异常,称为运行时异常,也称为非受检查异常 (Unchecked Exception)
RunTimeException 以及其子类对应的异常,都称为运行时异常 。例如上述我们举例的之前见过的异常: NullPointerException 、 ArrayIndexOutOfBoundsException、 ArithmeticException
注意:编译时出现的语法性错误,不能称之为异常。例如将 System.out.println 拼写错了 , 写成了
system.out.println. 此时编译过程中就会出错 , 这是 " 编译期 " 出错。而运行时指的是程序已经编译通过得到 class 文件了 , 由 JVM 执行过程中出现的错误.

三. 异常的处理

异常处理主要的 5 个关键字: throw try catch finally throws

3.1 异常的抛出throw

 Java中,可以借助throw关键字,由程序猿抛出一个指定的异常对象,将错误信息告知给调用者。具体语法如下:

throw new XXXException("异常产生的原因");

一般情况下, 通过throw抛出的是 自定义的异常, 可以自己通过类定义异常并抛出

例:实现一个获取数组中任意位置元素的方法。 

public static int getElement ( int [] array , int index ){
        if ( null == array ){
                throw new NullPointerException ( " 传递的数组为 null" );
        }
        if ( index < 0 || index >= array . length ){
                throw new ArrayIndexOutOfBoundsException ( " 传递的数组下标越界 " );
        }
        return array [ index ];
}
public static void main ( String [] args ) {
        int [] array = { 1 , 2 , 3 };
        getElement ( array , 3 );
}
注意事项
1. throw 必须写在方法体内部
2. 抛出的对象必须是 Exception 或者 Exception 的子类对象
3. 如果抛出的是 RunTimeException 或者 RunTimeException 的子类,则可以不用处理,直接交给 JVM 来处理
4. 如果抛出的是编译时异常,用户必须处理,否则无法通过编译
5. 异常一旦抛出,其后的代码就不会执行

3.2. 异常声明throws

处在方法声明时参数列表之后,当方法中抛出编译时异常,用户不想处理该异常,此时就可以借助 throws 将异常抛给方法的调用者来处理。即当前方法不处理异常,提醒方法的调用者处理异常
语法格式:
修饰符 返回值类型 方法名 ( 参数列表 ) throws 异常类型 1 ,异常类型 2 ...{
}

意思为:在这个方法中, 可能会包含这些异常, 告诉调用这个方法的人也就是程序猿去处理这些异常

如果程序猿不对异常进行处理, 那么就会交给JVM处理, 程序就会立刻停止.

 注意事项

1. throws 必须跟在方法的参数列表之后
2. 声明的异常必须是 Exception 或者 Exception 的子类
3. 方法内部如果抛出了多个异常, throws 之后必须跟多个异常类型,之间用逗号隔开,如果抛出多个异常类型具有父子关系,直接声明父类即可。

因为ArithmeticException是RuntimeException的子类, 所以只用写父类即可, 即:

4. 调用声明抛出异常的方法时,调用者必须对该异常进行处理,或者继续使用throws抛出

把光标方法波浪线处, 使用Alt+Enter 可以使用快捷键

 5. 如果throw Exception

这里的Exception是包含两种类型, 编译时异常和运行时异常, 所以编译器默认调用func()引发的是编译时异常  在main方法后也加上throw Exception, 此时才可能会变成运行时异常, 上JVM处理

3.3 捕获并处理try-catch

throws 对异常并没有真正处理,而是将异常报告给抛出异常方法的调用者,由调用者处理。如果真正要对异常进行处理,就需要try-catch
语法格式:
try {
        // 将可能出现异常的代码放在这里
} catch ( 要捕获的异常类型 e ){
        // 如果 try 中的代码抛出异常了,此处 catch 捕获时异常类型与 try 中抛出的异常类型一致时,或者是 try 中抛出异常的基类时,就会被捕获到
        // 对异常就可以正常处理,处理完成后,跳出 try-catch 结构,继续执行后序代码
}[ catch ( 异常类型 e ){
        // 对异常进行处理
        // 异常的处理方式
        //System.out.println(e.getMessage()); // 只打印异常信息
        //System.out.println(e); // 打印异常类型:异常信息
        e . printStackTrace (); // 打印信息最全面
} ]
// 后序代码
// 当异常被捕获到时,异常就被处理了,这里的后序代码一定会执行
// 如果捕获了,由于捕获时类型不对,那就没有捕获到,这里的代码就不会被执行
注意:
1. [] 中表示可选项,可以添加,也可以不用添加
2. try 中的代码可能会抛出异常,也可能不会

例:

 try中的代码发生数组越界, 通过数组越界异常进行捕捉, 所以捕捉到了, 就可以对异常进行处理, 处理后跳出try-catch结构, 继续执行后续代码, 所以运行结果为:

 若捕捉的是空指针异常:

即并未捕捉到, 所以就没有处理数组越界异常, 则交给JVM处理, 程序将立刻停止, 什么也不会打印

想要捕获数组越界异常, 继续catch, 自动匹配

第二种写法:(不推荐)

第三种写法:(不推荐)

注: 

1. 在try中发生异常后的代码不会被执行

2. 如果抛出异常类型与 catch 时异常类型不匹配,即异常不会被成功捕获,也就不会被处理,继续往外抛,直到JVM收到后中断程序 ---- 异常是按照类型来捕获的
3. try 中可能会抛出多个不同的异常对象,则必须用多个 catch 来捕获 ---- 即多种异常,多次捕获
4. 如果异常之间具有父子关系,一定是子类异常在前 catch ,父类异常在后 catch ,否则语法错误

 

finally

在写程序时, 有些特定的代码, 不论程序是否发生异常,都需要执行 ,比如程序中打开的资源 :网络连接、数据库连接、IO 流等, 在程序正常或者异常退出时,必须要对资源进进行回收 。另外,因为 异常会引发程序的跳转,可能 导致有些语句执行不到 finally 就是用来解决这个问题的。

 语法格式:

try {
        // 可能会发生异常的代码
} catch ( 异常类型 e ){
        // 对捕获到的异常进行处理
} finally {
        // 此处的语句无论是否发生异常,都会被执行到
}
        // 如果没有抛出异常,或者异常被捕获处理了,这里的代码也会执行

未发生异常:

 发生异常:

 体会资源回收:

另一种写法:

光标放在try上, Alt+Enter

注意:finally中的代码一定会执行的,一般在finally中进行一些资源清理的扫尾工作

// 下面程序输出什么?
public static void main ( String [] args ) {
        System . out . println ( func ());
}
public static int func () {
        try {
                return 10 ;
        } finally {
                return 20 ;
        }
}

//20

finally 执行的时机是在方法返回之前 (try 或者 catch 中如果有 return 会在这个 return 之前执行 finally). 但是如果finally 中也存在 return 语句 , 那么就会执行 finally 中的 return, 从而不会执行到 try 中原有的 return.
一般我们不建议在 finally 中写 return ( 被编译器当做一个警告 ).

 3.4异常的处理流程

首先了解一个概念:调用栈

调用栈:

方法之间是存在相互调用关系的, 这种调用关系我们可以用 "调用栈" 来描述. 在 JVM 中有一块内存空间称为"虚拟机栈" 专门存储方法之间的调用关系. 当代码中出现异常的时候, 我们就可以使用 e.printStackTrace(); 的方式查看出现异常代码的调用栈.  如果本方法中没有合适的处理异常的方式 , 就会沿着调用栈向上传递

 看下述代码:

在main方法中调用了func(), 在func()中出现了数组越界异常, 但是在func()方法中并没有处理异常, 于是沿着沿着调用栈向上传递到main方法中, 发现在main方法中处理了该异常, 所以不会交给JVM处理, 输出的结果为:

异常处理流程总结
1. 程序先执行 try 中的代码
2. 如果 try 中的代码出现异常 , 就会结束 try 中的代码 , 看和 catch 中的异常类型是否匹配 .
3. 如果找到匹配的异常类型 , 就会执行 catch 中的代码
4. 如果没有找到匹配的异常类型 , 就会将异常向上传递到上层调用者 .
5. 无论是否找到匹配的异常类型 , finally 中的代码都会被执行到 ( 在该方法结束之前执行 ).
6. 如果上层调用者也没有处理的了异常 , 就继续向上传递 .
7. 一直到 main 方法也没有合适的代码处理异常 , 就会交给 JVM 来进行处理 , 此时程序就会异常终止 .

 

四. 自定义异常类

Java 中虽然已经内置了丰富的异常类 , 但是并不能完全表示实际开发中所遇到的一些异常,此时就需要维护符合我 们实际情况的异常结构.
例如 实现一个用户登陆功能

 此时, 虽然我们可以很快的找到错误所在, 但代码一多, 就很难找到了, 所以, 我们要自定义异常类来帮助我们更快找到错误.

自定义异常通常会继承自 Exception 或者 RuntimeException
继承自 Exception 的异常默认是受查异常
继承自 RuntimeException 的异常默认是非受查异常

自定义异常类:

 接下来, 通过throw自己抛异常

 虽然, 我们抛出了异常, 但是为了使程序正常运行, 我们需要对异常进行处理:

今天的分享就到这里, 谢谢大家的点赞支持!! 

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

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

相关文章

设计模式之结构型模式(适配器、桥接、组合、享元、装饰者、外观、代理)

文章目录 一、结构型设计模式二、适配器模式三、桥接模式四、组合模式五、享元模式六、装饰者模式七、外观模式八、代理设计模式 一、结构型设计模式 这篇文章我们来讲解下结构型设计模式&#xff0c;结构型设计模式&#xff0c;主要处理类或对象的组合关系&#xff0c;为如何…

怎样实现燃气产业的数字化转型之路?

关键词&#xff1a;智慧燃气、燃气数字化、智慧燃气建设、智慧燃气解决方案、智慧燃气平台 燃气产业不仅是我国能源的支柱产业&#xff0c;更是推进经济建设与生态保护协同发展的主战场。数字技术与企业生产、经营及管理深度融合是驱动企业转型升级的重要路径。基于产业融合视…

【bash指令全集合】最全教程-持续更新!

作者&#xff1a;20岁爱吃必胜客&#xff08;坤制作人&#xff09;&#xff0c;近十年开发经验, 跨域学习者&#xff0c;目前于新西兰奥克兰大学攻读IT硕士学位。荣誉&#xff1a;阿里云博客专家认证、腾讯开发者社区优质创作者&#xff0c;在CTF省赛校赛多次取得好成绩。跨领域…

智慧工地源码 SaaS模式云平台

伴随着技术的不断发展&#xff0c;信息化手段、移动技术、智能穿戴及工具在工程施工阶段的应用不断提升&#xff0c;智慧工地概念应运而生&#xff0c;庞大的建设规模催生着智慧工地的探索和研发。 什么是智慧工地&#xff1f; 伴随着技术的不断发展&#xff0c;信息化手段、移…

基于Jenkins实现接口自动化持续集成

一、JOB项目配置 1、添加描述 可选选项可填可不填 2、限制项目的运行节点 节点中要有运行环境所需的配置 节点配置教程&#xff1a;https://blog.csdn.net/YZL40514131/article/details/131504280 3、源码管理 需要将脚本推送到远程仓库中 4、构建触发器 可以选择定时构建…

内衣迷你洗衣机什么牌子好?好用不贵的内衣洗衣机推荐

由于内衣洗衣机在目前的市场上越来越受欢迎&#xff0c;使得不少的小伙伴都在犹豫要不要为自己入手一台专用的内衣洗衣机&#xff0c;专门来清洗一些内衣裤等等贴身衣物&#xff0c;这个问题的答案是很有必要的&#xff0c;因为目前市场上的家用大型洗衣机对衣物只能够起到清洁…

AI 大模型爆发后,智能计算的需求有多强烈?

自从 ChatGPT 横空出世以来&#xff0c;AI 技术就成为科技领域备受关注的热门话题之一。据 OpenAI 的报告显示&#xff0c;自 2012 年以来&#xff0c;AI 大模型的规模呈指数级增长&#xff0c;其参数数量每 16 个月翻一番。 这些大型预训练模型&#xff0c;如 GPT-4、文心一言…

uniapp-hubildx配置

1.配置浏览器 &#xff08;1&#xff09;运行》运行到浏览器配置》配置web服务器 &#xff08;2&#xff09;选择浏览器安装路径 &#xff08;3&#xff09;浏览器安装路径&#xff1a; &#xff08;3.1&#xff09; 右键点击图标》属性 &#xff08;3.2&#xff09;选择目标&…

ubuntu安装kafka

一、前提&#xff0c;先去安装java环境 二、安装kafka wget http://www.apache.org/dyn/closer.cgi?path/kafka/2.8.0/kafka_2.13-3.6.0.tgz tar xzf kafka_2.13-3.6.0.tgz mv kafka_2.13-3.6.0 /usr/local/kafka // 这一步也可以不用 启动zookeeper sudo /usr/local/kafka_2…

ubuntu启动kafka报错Could not create the Java Virtual Machine.

网上有两种方式&#xff0c;但是需要具体看自己的错误信息&#xff0c;我的错误信息如下: 这里大概是说要写入日志无权限&#xff0c;所以执行的时候&#xff0c;前面加一下sudo 执行成功。

10.机器人系统仿真(urdf集成gazebo、rviz)

目录 1 机器人系统仿真的必要性与本篇学习目的 1.1 机器人系统仿真的必要性 1.2 一些概念 URDF是 Unified Robot Description Format 的首字母缩写&#xff0c;直译为统一(标准化)机器人描述格式&#xff0c;可以以一种 XML 的方式描述机器人的部分结构&#xff0c;比如底盘…

利用yolov5输出提示框,segment-anything生成掩膜实现图像的自动标注

文章目录 一. 创建环境二. 下载模型文件三. 编辑代码 一. 创建环境 anaconda下新建一个环境 conda create -n yolo-sam python3.8激活新建的环境 conda activate yolo-sam更换conda镜像源 conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/fre…

Hive SQL的各种join总结

说明 Hive join语法有6中连接 inner join&#xff08;内连接&#xff09;、left join&#xff08;左连接&#xff09;、right join&#xff08;右连接&#xff09;、full outer join&#xff08;全外连接&#xff09;、left semi join&#xff08;左半开连接&#xff09;、cr…

批量免费AI写作工具,批量免费AI写作软件

人工智能&#xff08;AI&#xff09;的应用在各个领域不断创新。面对繁重的写作任务,我们应该怎么完成&#xff1f;本文将专心分享批量免费AI写作的方法、工具以及选择时需要注意的事项。 批量免费AI写作的方法 利用开源AI模型 一种常见的批量免费AI写作方法是利用开源的AI模…

CUDA简介——CUDA内存模式

1. 引言 前序博客&#xff1a; CUDA简介——基本概念CUDA简介——编程模式CUDA简介——For循环并行化CUDA简介——Grid和Block内Thread索引 CUDA内存模式&#xff0c;采用分层设计&#xff0c;是CUDA程序与正常C程序的最大不同之处&#xff1a; Thread-Memory Correspondenc…

《数字中台建设总体方案》

《数字中台建设总体方案》 制定数字中台战略规划&#xff1a;制定符合企业实际情况的数字中台战略规划&#xff0c;明确建设目标、重点任务和时间表。确定数字中台架构&#xff1a;根据企业业务需求和特点&#xff0c;确定数字中台的架构&#xff0c;包括技术架构、应用架构和数…

vFW搭建IRF

正文共&#xff1a;2328字 40图&#xff0c;预估阅读时间&#xff1a;5 分钟 IRF&#xff08;Intelligent Resilient Framework&#xff0c;智能弹性架构&#xff09;技术通过将多台设备连接在一起&#xff0c;虚拟化成一台设备&#xff0c;集成多台设备的硬件资源和软件处理能…

Selenium自动化测试技巧还不知道吗?

1、前言 与以前瀑布式开发模式不同&#xff0c;现在软件测试人员具有使用自动化工具执行测试用例套件的优势&#xff0c;而以前&#xff0c;测试人员习惯于通过测试脚本执行来完成测试。 但自动化测试的目的不是完全摆脱手动测试&#xff0c;而是最大程度地减少手动运行的测试…

玻色量子计算应用奖公布!MathorCup大赛圆满落幕

2023年8月15日&#xff0c;中国优选法统筹法与经济数学研究会主办的2023年第十三届MathorCup高校数学建模挑战赛圆满落幕。为了培养优秀学子的创新意识及运用数学方法和量子计算技术解决实际问题的能力&#xff0c;推动量子计算的实际落地应用&#xff0c;北京玻色量子科技有限…

计算机网络:可靠数据传输(rdt)、流水协议、窗口滑动协议

文章目录 前言一、Rdt1.Rdt1.02.Rdt2.03.Rdt2.14.Rdt2.25.Rdt3.0 二、流水线协议1.滑动窗口&#xff08;slide window&#xff09;协议发送窗口接收窗口正常情况下的2个窗口互动异常情况下GBN的2个窗口互动异常情况下SR的2窗口互动GBN协议和SR协议的异同 2.小结 总结 前言 Rdt…