认识异常 ---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自己抛异常

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

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

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

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

相关文章

计算机类应届生简历10篇

计算机类应届生简历模板下载&#xff08;可在线编辑制作&#xff09;&#xff1a;来幻主简历&#xff0c;做好简历&#xff01; 计算机类应届生简历1&#xff1a; 求职意向 求职类型&#xff1a;全职 意向岗位&#xff1a;计算机相关工作 意向城市&#xff1a;广东广…

二维码智慧门牌管理系统升级:强化信息安全的防伪技术

文章目录 前言一、解决方案概览二、具体措施 前言 随着二维码智慧门牌管理系统在城市管理、企业形象展示和商铺门店等领域的广泛应用&#xff0c;信息安全问题愈发凸显。如何保障二维码门牌信息的安全性成为当前迫切需要解决的难题。 一、解决方案概览 专码专用&#xff1a;每…

【SQL 基础教程】w3school-SQL-基础知识-总结笔记

SQL-基础-笔记 一、简介 1&#xff1a;什么是 SQL&#xff1f; SQL 是用于访问和处理数据库的标准的计算机语言。 SQL 指结构化查询语言 SQL 使我们有能力访问数据库 SQL 是一种 ANSI 的标准计算机语言 2&#xff1a;SQL 能做什么&#xff1f; SQL 可在数据库中插入新的记录、删…

谢宁老师受邀在浙商企业家研习班中讲授华为战略规划SP实践(业务领先模型BLM)

随着全球经济持续的发展与变革&#xff0c;企业家们正面临着前所未有的挑战和机遇。如何在不断变化的市场环境中保持稳健发展&#xff0c;如何进行高效的投资&#xff0c;是众多企业家必须深思的重要问题。 为了协助企业家们更好地应对这些挑战&#xff0c;近日&#xff0c;在…

python超详细基础文件操作【建议收藏】

文章目录 前言1 文件操作1.1 文件打开与关闭1.1.1 打开文件1.1.2 关闭文件 1.2 访问模式及说明 2 文件读写2.1 写数据&#xff08;write&#xff09;2.2 读数据&#xff08;read&#xff09;2.3 读数据&#xff08;readlines&#xff09;2.3 读数据&#xff08;readline&#x…

前端模拟新闻列表ajax请求 mocky

效果图&#xff1a; <!DOCTYPE html> <html><head><meta charset"utf-8"><title></title> </head><style>ul {display: flex;flex-wrap: wrap;justify-content: space-between;}ul::after{content: ;width: 30%;}a…

数据结构——链表题目

文章目录 JZ25 合并两个排序的链表&#xff08;简单&#xff09;NC22 合并两个有序的数组&#xff08;简单&#xff09;NC3 链表中环的入口节点&#xff08;中等&#xff09;NC50 链表中的节点每k个一组翻转&#xff08;中等&#xff09;NC53 删除链表的倒数第n个节点(中等) JZ…

独立开发者都使用了哪些技术栈?

目录 一、前言 架构展示&#xff1a; 技术栈展示&#xff1a; 二、JNPF-JAVA-Cloud微服务 1.后端技术栈 2. 前端技术栈 Vue3技术栈 3. 数据库支持 一、前言 像独立开发者这类人群&#xff0c;也可以把他们理解为个人开发者/自由职业者。有一组数据显示&#xff0c;在美国&#…

冰 蝴 蝶

“冰蝴蝶”是一种自然景观&#xff0c;出现在每年的12月至次年2月间。在温度、湿度、风力、风向合适时&#xff0c;在山野间的枯草或灌木丛上会结出如“蝴蝶”一样的纤薄冰片&#xff0c;因此被称为“冰蝴蝶”。 受持续降温影响&#xff0c;12月3日&#xff0c;在山西闻喜县裴…

处理k8s中创建ingress失败

创建ingress&#xff1a; 如果在创建过程中出错了&#xff1a; 处理方法就是&#xff1a; kubectl get ValidatingWebhookConfiguration kubectl delete -A ValidatingWebhookConfiguration ingress-nginx-admission 然后再次创建&#xff0c;发现可以&#xff1a;

spdlog 简介与基础示例

0. 概况 0.1 源码搭建环境 源码网址&#xff1a; GitHub - gabime/spdlog: Fast C logging library. 可以只是用头文件&#xff0c;也可以先编译后使用&#xff1b;后面的示例都是直接使用头文件的方式。 编译方法&#xff1a; $ git clone https://github.com/gabime/spd…

vscode创建python虚拟环境

一、创建虚拟环境 python -m venv vsvenv 二、激活虚拟环境 cd .\myvenv\Scripts.\Activate.ps1 如果出现下图所示&#xff1a; 1、使用管理员运行PowerShell 2、输入命令&#xff1a;Get-ExecutionPolicy 3、输入命令&#xff1a;Set-ExecutionPolicy RemoteSigned&…

嵌入式设备里,SOC与MCU的区别是什么?

今日话题&#xff0c;嵌入式设备里&#xff0c;SOC与MCU的区别是什么?MCU与SOC有着明显的区别。MCU是嵌入式微控制器&#xff0c;而SOC则是片上系统。虽然这两者看似只有一个"嵌入式系统"的区别&#xff0c;但实际上在软件和硬件方面存在显著差异。首先&#xff0c;…

StarGAN 使用指南:一个模型实现多个域的迁移

StarGAN 使用指南 网络结构多数据集训练使用指南StarGAN v2 论文地址&#xff1a;https://arxiv.org/pdf/1711.09020.pdf 我们有猫的图片集、狗的图片集和兔子的图片集。 目标是让猫的图片看起来像狗的图片&#xff0c;狗的图片看起来像兔子的图片&#xff0c;兔子的图片看起…

面试前自测题,接口自动化测试过程中怎么处理接口依赖?

面试的时候经常会被问到在接口自动化测试&#xff0c;过程中怎么处理接口依赖&#xff1f;首先我们要搞清楚什么是接口依赖。 前言 01.什么是接口依赖 接口依赖指的是&#xff0c;在接口测试的过程中一个接口的测试经常需要依赖另一个或多个接口成功请求后的返回数据。 那怎么…

Stable Diffusion WebUI训练Lora测试XYZ显示例图

方式一 1.1 选择模型放入目录 将模型放入sd项目的models\Lora\目录,尽量保持和其他模型分开。 sd中显示如下: 1.2 脚本X/Y/Zplot选择 X轴类型:提示词搜索/替换 X轴值:NUM,000001,000002, 000003, 000004, 000005, 000006, 000007, 000008, 000009, 000010 Y轴类型:提…

Mysql进阶-事务锁

前置知识-事务 事务简介 事务 是一组操作的集合&#xff0c;它是一个不可分割的工作单位&#xff0c;事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求&#xff0c;即这些操作要么同时成功&#xff0c;要么同时失败。 就比如: 张三给李四转账1000块钱&#xff0…

文件下载保存接口的创建_FastAPI

文件下载保存接口的创建 功能描述实现代码功能演示 功能描述 在网页上对数据进行下载保存处理。例如点击网页上的保存按钮&#xff0c;会把文件下载到本地。下面就是对下载保存功能的实现。 实现代码 gpt_router.get("/export_data") async def export_data():# 需…

应用在触摸开关触控屏中的电容式触摸芯片

触摸开关是一种电子开关&#xff0c;使用时轻按开关按钮即可打开开关。松开手时&#xff0c;开关断开&#xff0c;内部结构由金属弹片受力弹动断开或者由电容值&#xff0c;电阻值等电气参数改变而控制。触摸开关一般是指应用触摸感应芯片原理设计的一种墙壁开关&#xff0c;是…

nginx部署和安装-后端程序多端口访问-后端代理设置

部分补充 查看nginx是否安装http_ssl_module模块 ./nginx -V 看到有 configure arguments: --with-http_ssl_module, 则已安装。 如果没有安装&#xff1a;参考文档 nginx官网地址&#xff1a;nginx: download 这里下载nginx-1.18.0稳定版tar.gz 下载后&#xff0c;利用…