Java---认识异常

欢迎大家来观看本博课------Java------认识异常。1.异常的概念和体系结构

1.异常的概念和体系结构 

1.1 异常的概念

在Java中,在程序执行过程中发生的不正常行为称为异常。如在之前我们经常遇到的算数异常(ArithmeticException)、数组越界异常(ArrayIndexOutOfBoundsException)和空指针异常(NullPointerException )。

1.2 异常的体系结构

在Java中,异常是一种类。由于异常的种类太多了,为了对异常和错误进行很好的分类管理,Java内部维护了一个异常的体系结构。

如下图

从上图可以看出异常的种类众多

1. Throwable位于最高层,是所有异常和错误的父类,派生出了Exception和Error两个子类。

2. Error是指Java虚拟机无法解决的严重问题。

3. Exception是指程序在发生不正常行为后,程序员可以通过调整代码,是程序正常运行。

1.3 异常的分类

异常分为两种,分别为编译时异常和运行时异常。

1.编译时异常

编译时异常也被称为受检查异常。即程序没运行时,编译器就会划红线报异常。

以我们之前讲的克隆为例子

如上图,程序都还没运行,编译器就会划红线报异常了,这就是编译时异常。

2.运行时异常

 运行时异常也被称为不受查异常,即在程序运行之后才会出现的异常。

如以上代码,程序运行前没有出现任何异常,但是运行代码后,就会报出下图的异常。这就是所谓的运行时异常。 

2. 异常的处理

 在Java中,关于异常的处理我们要用带5个关键字,分别为throw,try,catch,finally和throws

1. 异常的抛出----throw

public class Test {
    private static void func(int a){
        if(a==0){
            throw new ArithmeticException();
        }
    }
    public static void main(String[] args) {
        func(0);
    }
}

运行以上代码

public class Test {
    private static void func(int a){
        if(a==0){
            throw new ArithmeticException("a==0");
        }
    }
    public static void main(String[] args) {
        func(0);
    }
}

 以上个代码的区别在哪呢?就是一个抛出的异常传了参数,一个没有传参数。

这个传递的字符串通常是产生异常的原因。如果传来参数,运行的时候,字符串也会显示出来。

【注意事项】

1. throw必须写在方法的内部。

2.throw抛出的异常需要是Exception类或者是Exception的子类。

3.如果throw抛出的异常是运行时异常,可以不写,最后交给JVM来处理。

4.如果throw抛出的是编译时异常,则程序员必须处理,否则程序无法运行。

5.throw一但抛出,后续代码将不会运行。

6.throw抛出的一般是自定义异常。(软性要求)

2.异常的捕获

异常的捕获,也就是异常的处理方式。通常是异常声明---throws关键字和异常捕获try-catch两种。

1.异常声明---throws关键字

异常申明一般处于方法的参数列表的后面,如果程序不想亲自解决该方法声明的异常,我们可以将该异常抛给方法的调用者来处理。即当前的方法不处理异常,让方法的调用来处理异常

以之前实现对象的克隆为例子:

之前我们实现克隆的时候为什么到这一步还会保错呢?

因为我们在调用clone这个方法的时候,这个clone方法声明了一个异常,需要该方法的调用者来处理这个异常。明显是在main方法中调用了该clone方法,所以main方法要来处理这个异常。处理方式就是也在方法的调用者的方法参数列表后面在声明一次该异常就行了。

如下图

【注意事项】

1.throws的异常声明只能写在函数参数列表的后面。

2.throws声明的异常必须是Exception类或者Exception的子类。

3.如果方法内部抛出了多个异常,throws后面就得写多个异常,中间用逗号隔开。如果异常的类型之间存在父子类的关系,则只声明也可以。  

2.异常的捕获并处理----try{...}catch(...){...}

throws声明的异常并没有对异常进行真正的处理,如果想真正得对异常进行处理,需要用到try和catch关键字。

语法格式

try{
   ...
}catch(){
   ...
}

代码演示

public static void func(){
     int[] arr={1,2,3};
        System.out.println(arr[4]);
    }
    public static void main(String[] args) {
        try{
            func();
        }catch (ArrayIndexOutOfBoundsException e){
            System.out.println("捕获数组越界异常");
            e.printStackTrace();
        }

    }

从上面代码,我们知道func()方法里面出现了数组越界的异常,我们将出现异常的代码放在try的代码块里面,接着在catch的括号里面写上对应出现的异常。

【注意事项】

1.try...catch中可以根多种异常,知道与catch后的异常类型匹配为止。

public static void func(){
     int[] arr={1,2,3};
        System.out.println(arr[4]);
    }
    public static void main(String[] args) {
        try{
            func();
        }catch (NullPointerException e){
            System.out.println("捕获了空指针异常");
            e.printStackTrace();
        }catch (ArithmeticException e){
            System.out.println("捕获了算术异常");
            e.printStackTrace();
        }catch (ArrayIndexOutOfBoundsException e){
            System.out.println("捕获数组越界异常");
            e.printStackTrace();
        }
    }

如上面的代码,虽然也写了catch很多异常,但是抛出的异常是数组越界异常,所以只会执行与数组越界异常匹配的catch语句。

 2.如果try里面的代码块里的代码出现了异常,那么try代码块就不会执行出现异常代码之后的代码但如果try代码块里面不出现异常,则try代码块里面的所有代码都会执行。

public static void func(){
     int[] arr={1,2,3};
        System.out.println(arr[4]);
    }
    public static void main(String[] args) {
        try{
            func();
            System.out.println("func()后面的代码");
        }catch (ArrayIndexOutOfBoundsException e){
            System.out.println("捕获数组越界异常");
            e.printStackTrace();
        }
    }

由于func()抛出了异常,所以就不会执行try代码块里面func()后面的代码。

3. 只有捕捉到了异常,catch代码块里面的的代码才会运行。

public static void main(String[] args) {
        try{
            int n=10;
        }catch (ArrayIndexOutOfBoundsException e){
            System.out.println("捕获数组越界异常");
            e.printStackTrace();
        }
    }

 由于try代码快里面的代码没有出现异常,则catch就没有捕获异常,则catch代码快里面的代码就不会运行。

4.如果try代码块里面抛出了多个异常,只会捕捉一个异常,因为当捕捉了一个代码之后,代码就会终止了。

3.finally关键字

在程序运行的时候,会有一些特定的代码,不管程序是否抛出异常,都需要执行。比如程序资源的打开:网络连接、数据库连接和IO流。在程序正常运行或者出现异常时,必须实现对资源的关闭,否则会造成内存泄漏。另外,可能因为程序抛出异常,会导致一些代码执行不了。这时候就要用到finally关键字。因为finally代码块里面不管前面的代码是否抛出异常,finally代码块里面的代码都会执行。

1. 程序抛出异常

public static void main(String[] args) {
        int[] arr={1,2,3};
        try{
            arr[4]=0;
        }catch (ArrayIndexOutOfBoundsException e){
            System.out.println("捕获到数组越界异常");
        }finally {
            System.out.println("finally代码块运行");
        }
    }

运行代码 

 2. 程序不抛出异常

public static void main(String[] args) {
        int[] arr={1,2,3};
        try{
            arr[2]=0;
        }catch (ArrayIndexOutOfBoundsException e){
            System.out.println("捕获到数组越界异常");
        }finally {
            System.out.println("finally代码块运行");
        }
    }

 3. 易错点

public static int func(){
        try{
            return 20;
        }catch (ArrayIndexOutOfBoundsException e){
            System.out.println("捕获到数组越界异常");
        }finally {
            return 100;
        }
    }
    public static void main(String[] args) {
       int data= func();
        System.out.println(data);//打印100
    }

之所以最后的结果是100,我们可以理解为因为finally代码块终究会执行,所以程序就会只执行finally代码块里面的return语句。 

 4. 异常处理总结

首先会执行try代码块里面的代码,看其是否抛出异常。如果抛出异常,就会看catch代码块有没有匹配的异常,如果catch边没有找到对应的异常,就会交给上层调用者去处理。如果上层调用者也没有处理异常,则会交给main方法处理,如果main方法也没有处理,则最后就会交给JVM去处理。

3.自定义异常类

虽然在Java中,异常的种类也很丰富了,但终会有一些异常在Java中是没有定义的,所以我们要学会自定义异常类。

1. 自定义异常一般都会继承Exception类或者RunTimeException类。

2. 继承Exception类是受检查类。

3. 继承RunTimeException类是不受检查类。

实现登录异常

自定义NameExcetion类继承Exception

public class NameException extends Exception{
    public NameException() {
        super();
    }

    public NameException(String message) {
        super(message);
    }
}

自定义Password类继承RuntimeException

public class PasswordException extends RuntimeException{
    public PasswordException() {
        super();
    }

    public PasswordException(String message) {
        super(message);
    }
}

主函数

class Login {
    public String password;
    public String name;

    public Login(String password, String name) {
        this.password = password;
        this.name = name;
    }
    public  void login(String password,String name)throws PasswordException,NameException{
        if(!this.password.equals(password)){
            throw new PasswordException("密码错误");
        }if(!this.name.equals(name)){
                throw new NameException("用户名错误");
            }
        System.out.println("登录成功");
        }
}
public class Test {
    public static void main(String[] args) {
        Login login=new Login("123","man");
        try{
            login.login("123","man");
        }catch (PasswordException e){
            e.printStackTrace();
        }catch (NameException e){
            e.printStackTrace();
        }
    }
}

我们也可以在login函数处理继承Exception类抛出的异常。

class Login {
    public String password;
    public String name;

    public Login(String password, String name) {
        this.password = password;
        this.name = name;
    }
    public  void login(String password,String name){
        if(!this.password.equals(password)){
            throw new PasswordException("密码错误");
        }try {
            if(!this.name.equals(name)){
                throw new NameException("用户名错误");
            }
        }catch (NameException e){
            e.printStackTrace();
        }
        System.out.println("登录成功");
    }
}
public class Test {
    public static void main(String[] args) {
        Login login=new Login("123","man");
        try{
            login.login("123","man");
        }catch (PasswordException e){
            e.printStackTrace();
        }
    }
}

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

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

相关文章

[环境配置]vscode通过ssh连接autodl进行项目开发

警告:如果使用VSCode直接执行或开终端执行训练程序,请在调试完成后最后通过screen/tmux工具开守护进程,确保程序不受SSH连接中断影响程序执行! 官方文档:请戳 AutoDL使用方法: 在进行操作前您需要提前安装…

swagger生成离线接口文档

官方网站 https://editor-next.swagger.io/ 上传接口文件 生成 生成之后的效果

盲盒App开发时有哪些技术框架可以借鉴

在开发盲盒App时,技术框架的选择对于应用的性能、稳定性和用户体验都至关重要。以下是几个可以借鉴的技术框架,它们在不同方面提供了优势,并且结合了参考文章中的相关信息: 前端技术框架 微信小程序框架: 优点&#…

R可视化:微生物相对丰度或富集热图可视化

欢迎大家关注全网生信学习者系列: WX公zhong号:生信学习者Xiao hong书:生信学习者知hu:生信学习者CDSN:生信学习者2介绍 热图(Heatmap)是一种数据可视化方法,它通过颜色的深浅或色调的变化来展示数据的分布和密度。在微生物学领域,热图常用于表示微生物在不同分组(如…

node更改npm缓存存储位置-并配置环境变量

更改缓存位置 node安装完成之后,在安装目录中新建一个存放缓存的文件夹node_cache 此时这个文件夹必须使用管理员权限才能更改,这使得命令行下使用npm进行下载的时候总是报权限不足的错误:permit 解决办法: 右键 -> 属性 -> 安全 -> 编辑 -> 选择user -> …

小程序外卖开发中的关键技术与实现方法

小程序外卖服务凭借其便捷性和灵活性,正成为现代餐饮行业的重要组成部分。开发一个功能完善的小程序外卖系统,需要掌握一系列关键技术和实现方法。本文将介绍小程序外卖开发中的核心技术,并提供具体的代码示例,帮助开发者理解和实…

Centos离线安装Python3

目录 1.准备工作 2.解压python压缩包 3.编译 4.安装、更改环境变量 5.建立pip连接 使用的是Centos7服务器,Py版本是py3.9.0 1.准备工作 首先确保服务器中存在相关的编译器,例如GCC;这里不做过多叙述,需要者前往&#xff1a…

差分个人见解(一)

差分个人见解(一) 一维差分什么是差分构造差分数组差分数组的用处实战演练题目 一维差分 什么是差分 前缀和或许你已经了解了,差分其实就是前缀和的逆运算。 假设 a1 到 an 为 b1到 bn 的前缀和。 那么 b1 到 bn,分别就是 a1 到…

2024企业AI应用行动指南(PPT可下载)

如需下载本方案PPT/WORD原格式,诚挚邀请您微信扫描以下二维码加入方案驿站知识星球,获取上万份PPT/WORD解决方案!!!感谢支持!!!

618有哪些好物值得购买?这五款超值科技数码产品别错过!

一年一度的618购物狂欢节即将到来,这是消费者们选购心仪商品的绝佳时机。在众多产品中,科技数码产品一直以来都是备受关注的领域。 它们不仅代表着当下最前沿的技术,还能为我们的生活带来诸多便利。本文将为您推荐五款在618期间值得购买的超值…

【全开源】ChatGPT 机器人公众号小程序h5源码开源交付支持二开

AI机器人系统对接OPENAI:智能互联的无限可能 🌐 一、引言:AI机器人系统与OPENAI的碰撞 在科技日新月异的今天,AI机器人系统正逐渐渗透到我们生活的各个角落。而当这一智能系统与全球领先的OPENAI技术相结合,又将擦出…

Javaweb---IDEA中使用TomCat插件问题

引言 众所周知我们日常web开发的时候每次对内容进行修改就必须新打一次war包,这个过程太过繁琐,为了大大减少这些步骤,我们使用IDEA中的插件Smart TomCat(如下图所示)这个插件就是把tomcat搬到idea中了,大大减少我们的工作量 操作非常简单,直接install即可,如若无法使用可以重…

轻易云-轻企AI知识库的智能创作与个性化管理

随着人工智能技术的飞速发展,AI助手正逐渐成为我们生活和工作中不可或缺的伙伴。轻易云AI助理,作为这一领域的佼佼者,以其无所不知、无所不能的AI创作模型,为用户带来了前所未有的智能体验。 一、AI创作模型的丰富性 在轻易云AI助…

摄影构图:如何处理对焦、快门、光圈、ISO 以及拍摄方式

写在前面 博文内容涉及摄影对焦模式、快门速度、光圈、ISO以及拍摄方式的简单介绍《高品质摄影全流程解析》 读书笔记整理理解不足小伙伴帮忙指正 😃 生活加油 99%的焦虑都来自于虚度时间和没有好好做事,所以唯一的解决办法就是行动起来,认真…

ZYNQ7 Processing System IP核中PS侧Uart的用法

在ZYNQ7 Processing System IP核中集成的UART控制器是一个中全双工异步接收器和发送器,支持广泛的可编程波特率和I/O信号格式,可以适应自动奇偶校验生成和多主机检测模式。 UART操作由配置和模式寄存器控制。使用状态寄存器、中断状态寄存器和调制解调器…

功能测试 之 单模块测试----轮播图、登录、注册

单功能怎么测? 需求分析 拆解测试点 编写用例 1.轮播图 (1)需求分析 位置:后台--页面--广告管理---广告列表(搜索index页面增加广告位2) 操作完成后需要点击admin---更新缓存,前台页面刷新生效 (2)拆解…

基于梯度下降的多元线性回归原理

为了展示多元线性回归的迭代过程,我们可以使用梯度下降算法手动实现多元线性回归。梯度下降是一种迭代优化算法,用于最小化损失函数。 我们将以下步骤进行手动实现: 初始化回归系数。计算预测值和损失函数。计算梯度。更新回归系数。重复步…

WebMvcConfigurer配置不当导致鉴权失败

最近同事说他们有个新需求,需要对接口进行加解密,所以他给项目配置了一个拦截器,但这个拦截器直接导致了每个接口鉴权失败,每次调用接口都是提示没有session信息。 公司内的所有java项目是公用同一套基础依赖,所以我也…

差分个人见解(二)

差分个人见解(二) 二维差分二维差分数组的用途构造二维差分数组实战演练 如果你还不太熟悉一维差分,那么请先学会一维差分。 二维差分 二维差分数组的用途 在一维差分数组中,它的用途是 快速 使一个区间内加上一个数。 那么二…

【产品经理】订单处理2

本次讲解订单初始化成功到ERP系统过程中的后续环节。 一、根据客服备注更新订单信息 初始化订单过程中,若订单中的客服备注信息对订单进行更新,包括可能改收货信息、改商品、加赠品、指定快递等。 注意:更新订单的过程中要注意订单当前状…