带你深入理解Java异常

news2024/11/26 4:39:38

💕“人生就像一盘棋,有时候你慢一步,就输掉了一局。但只要你不停止思考和行动,就永远有机会翻盘。”💕
🐼作者:不能再留遗憾了🐼
🎆专栏:Java学习🎆
🏀本文章主要内容:详细讲解Java异常🏀
在这里插入图片描述

文章目录

  • 什么是异常
    • 受查异常
    • 非受查异常
  • 怎样处理异常
    • 事前防御型异常
    • 事后认错型异常
    • 异常的抛出
    • 异常的捕获
      • throws捕获异常
      • try-catch-finally捕获异常
        • finally
  • 自定义异常类

什么是异常

在这里插入图片描述

Java是一种面向对象编程语言,提供了一种强大的异常处理机制。Java异常是一个事件,它发生在程序执行过程中导致程序中断或出错。当发生异常时,Java程序会自动创建一个异常对象来表示该异常,并将异常对象传递给相应的异常处理程序来处理。

Java异常机制的主要目的是使程序更加可靠,因为在发生异常时,程序并不会异常终止,而是将异常传递给异常处理程序来处理。Java异常处理机制提供了一种强大的工具,使得程序能够处理错误情况,以便程序可以回复并继续执行。在Java中,异常可以分为两种类型:受查异常和非受查异常。

受查异常

受查异常也叫编译异常,是指在编译时必须显式地声明抛出该异常,否则编译器将会报错。受查异常通常是程序可以预料到并可能解决的异常,例如文件不存在、网络连接异常等。如果程序在编译时没有正确地处理受查异常,将会导致编译错误。

下面是一个示例代码,它使用了Java的IOException异常,这是一种受查异常。

import java.io.*;

public class FileHandling {
   public static void main(String args[]) {
      try {
         File file = new File("file.txt");
         FileReader fr = new FileReader(file);
         BufferedReader br = new BufferedReader(fr);
         String line;
         while((line = br.readLine()) != null) {
            System.out.println(line);
         }
         br.close();
      } catch(IOException e) {
         e.printStackTrace();
      }
   }
}

在上面的代码中,我们通过FileReader读取文件内容,并使用BufferedReader逐行读取文件内容。由于读取文件时可能会发生异常,我们需要在try-catch块中捕获并处理IOException异常。

非受查异常

非受查异常是指在编译时无须声明抛出该异常。通常情况下,非受查异常是由于程序中出现了错误,例如除数为零、数组下标越界等,并且发生这些异常时,程序无法自行恢复。因此,非受查异常通常会导致程序异常终止。

在Java中,非受查异常包括RuntimeException及其子类,例如NullPointerException(空指针异常)、ArrayIndexOutOfBoundsException(数组越界异常)、ArithmeticException(除数为0异常)等。这些异常通常是程序出现逻辑错误时才会产生。

下面是一个示例代码,它使用了Java的ArithmeticException异常,这是一种非受查异常。

public class Example {
   public static void main(String args[]) {
      int a = 10, b = 0;
      try {
         int c = a / b;
         System.out.println("Result: " + c);
      } catch(ArithmeticException e) {
         System.out.println("Exception caught: " + e);
      }
   }
}

在上面的代码中,我们尝试将10除以0,这会导致ArithmeticException异常的发生。由于程序无法自行恢复该异常,我们需要在try-catch块中捕获并处理该异常。

当出现异常的时候,我们必须自己手动处理这些异常,否则这些异常就会交给JVM处理,如果交给JVM处理,那么程序就会异常终止。

举个不恰当的例子,当你犯事的时候,如果只是你的父母发现知道了,那么你的父母可能会帮助你解决问题并且不告诉警察;但是如果你的父母不知道,但是被警察知道了,那么你就会被法律制裁。

怎样处理异常

事前防御型异常

Java中的事前防御型异常(Proactive Defense)指的是在代码开发阶段预先考虑和处理异常情况,以提高应用程序的健壮性和稳定性。事前防御型异常意味着通过将异常情况纳入代码设计和实现过程,尽可能主动地防止异常情况的发生,而不仅是在异常发生后采取响应措施。

意思也就是说:我根本不给你犯罪的机会,从你有这个萌芽的时候就扼杀你。

	public static int length(String s) {
        if(s == null) {
            return -1;
        }
        return s.length();
    }

    public static void main(String[] args) {
        System.out.println(length("abdias"));
    }

当我们用length来求字符串的长度时(有点多此一举了啊),你想要访问null的时候,我直接终止这个length,不让你访问null。这就是事前防御型异常。

事后认错型异常

Java中的事后认错型异常(Post-mortem Defense)是指在应用程序运行时发生异常时采取的响应措施。如果应用程序无法避免发生异常情况,那么事后认错型异常就是在程序发生异常后对异常进行收集和处理,以恢复应用程序的稳定性和可靠性。

Java中可以使用try-catch-finally块来捕获和处理发生的异常。try块中包含可能会引发异常的代码,catch块用于捕获处理异常情况,finally块用于确保代码块中的资源得到释放(即使异常发生)。

try {
	可能会出现异常的代码块
}catch(捕获的异常) {
	处理异常
}finally {
	确保代码块中的资源得到释放
}

我们今天主要讲的就是事后认错型异常。

异常的抛出

我们使用throw关键字来抛出一个指定的异常对象。

	public static int length(String s) {
        if(s == null) {
            throw new NullPointerException("字符串引用指向null");
        }
        return s.length();
    }

    public static void main(String[] args) {
        System.out.println(length(null));
    }

在这里插入图片描述
这里会将你出错的位置给你指出来,方便改正。

我们再来思考一个问题,就是如果这里抛出异常了,那么当出现异常的时候,其后面的代码还会执行吗?

public static int length(String s,int a) {
        if(s == null) {
            throw new NullPointerException("字符串引用指向null");
            a = 20;
        }
        return s.length();
    }

    public static void main(String[] args) {
        int a = 10;
        System.out.println(length(null,a));
        System.out.println(a);
    }

在这里插入图片描述
这里标红了,我们将鼠标放上去,可以看到提示,提示这个语句是不可能达到的,也就是说,当你s指向的不为null时,if语句根本就进不去,如果s指向的是null时,程序也不会走到a = 20这个语句,所以抛出异常的语句如果出现了异常,那么后面的语句将不会执行。

注意事项
1. throw必须写在方法体内部
2. 抛出的对象必须是Exception 或者 Exception 的子类对象
3. 如果抛出的是 RunTimeException 或者 RunTimeException 的子类,则可以不用处理,直接交给JVM来处理
4. 如果抛出的是编译时异常,用户必须处理,否则无法通过编译
5. 异常一旦抛出,其后的代码就不会执行

异常的捕获

throws捕获异常

当你在方法参数的后面使用throws异常类型时,表明你这个方法可能会出现此类异常,但是在此方法中不处理异常,只是告诉你调用者会出现异常,具体怎样处理,需要你调用者处理。

	public static int length(String s) throws NullPointerException{
        if(s == null) {
            throw new NullPointerException("字符串引用指向null");
        }
        return s.length();
    }

    public static void main(String[] args) {
        int a = 10;
        System.out.println(length(null));
        System.out.println(a);
    }

就先这样,我length方法只是告诉你出现了空指针异常,但是空指针异常解决了吗?并没有,所以我们在方法参数后面使用throws 异常类型只是告诉调用者会出现那种类型的异常,具体解决需要调用者解决。如果你调用者没有解决异常,那么就需要继续用throws抛出异常。

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

如果我们想要解决这个异常该怎么办呢?

try-catch-finally捕获异常

try{
// 将可能出现异常的代码放在这里
}catch(要捕获的异常类型 e){
// 对异常就可以正常处理,处理完成后,跳出try-catch结构,继续执行后序代码
}catch(异常类型 e){
// 对异常进行处理
}finally{
// 此处代码一定会被执行到
}
// 后序代码
// 当异常被捕获到时,异常就被处理了,这里的后序代码一定会执行
// 如果捕获了,由于捕获时类型不对,那就没有捕获到,这里的代码就不会被执行

当try中的代码出现异常的时候,catch就会捕获try中出现的异常,并且对应的catch捕获的异常类型是与try中抛出的异常类型一致,或者是try中抛出异常的基类,当某个catch捕获到了对应的异常时,如果catch中的代码块执行完后,就会跳出其他的catch捕获到finally(如果有),否则就到后续的代码块,也就是说catch只能捕获到一种异常。

public static int length(String s) throws NullPointerException{
        if(s == null) {
            throw new NullPointerException("字符串引用指向null");
        }
        return s.length();
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String str = null;
        int ret = 0;
        try {
            ret = length(str);
        }catch(NullPointerException e) {
        	//e.printStackTrace将栈上出现的异常给打印出来
            e.printStackTrace();
            System.out.println("传入的字符串为null,请重新输入");
            String tmp = scanner.nextLine();
            ret = length(tmp);
        }
        System.out.println(ret);
    }

在这里插入图片描述

注意事项
1. try块内抛出异常位置之后的代码将不会被执行
2. 如果抛出异常类型与catch时异常类型不匹配,即异常不会被成功捕获,也就不会被处理,继续往外抛,直到JVM收到后中断程序----异常是按照类型来捕获的。
3. try中可能会抛出多个不同的异常对象,则必须用多个catch来捕获----即多种异常,多次捕获。
4. 可以通过一个catch捕获所有的异常,即多个异常,一次捕获(不推荐)

catch (ArrayIndexOutOfBoundsException | NullPointerException e) { ... }
5.如果异常之间具有父子关系,一定是子类异常在前catch,父类异常在后catch,否则语法错误。

finally

finally中的代码是一定会被执行的,不管你的try中有没有出现异常,就算你在catch捕获异常并处理异常的时候return了,finally中的代码也是会出现在程序结束之前。
finally通常被用在网络连接数据库连接、IO流等,在程序正常或者异常退出时,必须要对资源进行回收。另外,因为异常会引发程序的跳转,可能导致有些语句执行不到,finally就是用来解决这个问题的。

自定义异常类

当我们平时登录账号的时候,如果用户名或者密码错误的时候,我们又该抛出怎样的异常呢?

Java中提供了非受查类异常NullPointerException(空指针异常)、IndexOutOfBoundsException(数组越界异常)、IllegalArguementException(无效参数异常)、ClassCastException(类型转换异常)等。这些在我们的日常生活中显然是不能完全覆盖到的,所以就出现了自定义异常,我们可以自己定义异常。

当我们自定义异常类的时候,我们需要继承Exception类或者Exception的子RunTimeException,建议继承RunTimeException。

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

public class Main {


    private static String name = "zhangsan";
    private static String ps = "123456";
    public static void login(String name,String ps) {
        if(!Main.name.equals(name)) {
            throw new NameException("用户名错误");
        }
        if(!Main.ps.equals(ps)) {
            throw new PasswordException("密码错误");
        }
    }


    public static void main1(String[] args) throws NameException,PasswordException{
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入你的用户名和密码");
        String name  = scanner.nextLine();
        String ps = scanner.nextLine();
        try {
            login(name,password);
        }catch(NameException e) {
            e.printStackTrace();
        }catch(PasswordException e) {
            e.printStackTrace();
        }
    }

class NameException extends RuntimeException {
    public NameException(String message) {
        super(message);
    }
}

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

在这里插入图片描述
在这里插入图片描述

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

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

相关文章

《计算机网络——自顶向下方法》精炼——3.4.1-3.4.3

聪明出于勤奋,天才在于积累。——华罗庚 文章目录 对协议的进一步改进rdt2.1rdt2.2rdt3.0:含有比特差错和丢包的可靠数据传输协议 流水线协议回退n步(GBN) 对协议的进一步改进 rdt2.1 在上一篇文章中,我们讲到对于产生比特差错的…

A2-RIDE Long-tailed recognition by routing diverse distribution-aware experts

文章目录 0. Abstract1. Introduction2. Related Works3. RIDE:ROUTING DIVERSE DISTRIBUTION-AWARE EXPERTS4. Experiments5. Summary论文总结长尾数据分布 (Long-tailed Data Distribution)RIDE方法及模型1. **Multi-expert framework**2. **Routing diversified …

RabbitMQ如何保证顺序消费

目录标题 生产者有序的情况下如何保证顺序生产单个消费者多个消费者 生产者无序的情况下消息返回队列消息不返回队列 生产者有序的情况下 如何保证顺序生产 单一生产者:消息生产的顺序性仅支持单一生产者。 串行发送:如果生产者采用多线程并行发送&…

借助国内ChatGPT平替+markmap/Xmind飞速生成思维导图

系列文章目录 借助国内ChatGPT平替MindShow,飞速制作PPT 文章目录 系列文章目录前言一、科大讯飞“星火”认知大模型二、使用步骤1.借助讯飞星火生成思维导图的文案2.选择markmap绘制思维导图3.选择Xmind绘制思维导图 总结 前言 随着人工智能技术的不断发展&#x…

自动操作魔法师4.9.0.0

产品下载 (won-soft.com) 如下图所示: 彻底远离枯燥乏味的工作 在日常办公中,开发票,更新客户资料,打印报表,录入数据等等工作是极为重要,但大部分时候这些工作是相当枯燥的。你不得得一遍又一遍的进行重复…

第二章: Mybatis-Plus 快速入门

目录 1. 准备工作 数据库准备: 创建Maven 父模块 2. Mybatis 整合 Mybatis-Plus 创建子模块: 准备 log4j.properties 日志文件 3. Mybatis 原生写法实现查询User 编写mybatis-config.xml文件: 编写User实体对象:(这里使用lombok进行了…

Hyper-V搭建免费桌面云

Hyper-V 是 Microsoft 的硬件虚拟化产品。 它用于创建并运行计算机的软件版本,称为“虚拟机”。 每个虚拟机都像一台完整的计算机一样运行操作系统和程序。 如果需要计算资源,虚拟机可提供更大的灵活性、帮助节省时间和金钱,并且与在物理硬件…

【AI面试】RoI Pooling 和 RoI Align 辨析

RoI Pooling和RoI Align是两种常用的目标检测中的RoI特征提取方法。它们的主要区别在于:如何将不同大小的RoI对齐到固定大小的特征图上,并在这个过程中保留更多的空间信息。 一、RoI Pooling RoI Pooling最早是在Fast R-CNN中提出的,它的基…

MySQL MHA

概述 什么是 MHA MHA(Master High Availability)是一套优秀的MySQL高可用环境下故障切换和主从复制的软件。 MHA 的出现就是解决MySQL 单点的问题。 MySQL故障切换过程中,MHA能做到0-30秒内自动完成故障切换操作。 MHA能在故障切换的过程中…

JAVA语言-比较器Comparator(java中Comparable和Comparator的区别)

文章目录 一、什么是Comparator二、Java compare方法和compareTo方法三、java中Comparable和Comparator的区别 Comparator的例子三、demo:java8使用Lambda表达式比较器Comparator给List对象排序,按时间、数字、字典排序 一、什么是Comparator Comparato…

Unittest单元测试框架之unittest_执行用例的详细信息

unittest_执行用例的详细信息 用unittest.main()执行测试集 这里的verbosity是一个选项,表示测试结果的信息复杂度,有三个值:0 (静默模式): 你只能获得总的测试用例数和总的结果 比如 总共100个 失败20 成功801 (默认模式): 非常类似静默模式 只是在每…

MySQL数据库从入门到精通学习第3天(查看,选择,修改,删除数据库)

查看,选择,修改,删除数据库 查看数据库选择数据库修改数据库删除数据库 查看数据库 创建完数据库,可以通过SHOW命令来查看所有的数据库信息,语法: SHOW DATABASES [LIKE %模式% WHERE 条件]; >>>…

MySQL进阶-索引

本文介绍MySQL索引的结构、语法、使用规则等 文章目录 索引介绍索引结构二叉树B-TreeBTreeHash 索引分类思考题 语法SQL性能分析SQL的执行频率慢查询日志PROFILE详情EXPLAIN执行计划 索引使用规则最左前缀法则索引失效情况索引列运算字符串不加引号模糊查询or连接的条件数据分布…

(免费分享)基于微信小程序的旅游系统

目 录 1绪论 1 1.1概述 1 1.2课题意义 2 1.3主要内容 2 2 相关技术简介 3 2.1 HBuilder X技术介绍 4 2.2 JAVA简介 5 2.3 MYSQL数据库 6 2.4 SSM框架 7 3 系统分析 8 3.1 系统需求分析 9 3.1.1系统功能需求 10 3.1.2系统技术需求 11 3.1.3系统安全需求 12 3.2 可行性分析 13 3…

postgresql 词法/语法(scanner/parser)中flex/bison介绍

专栏内容:postgresql内核源码分析个人主页:我的主页座右铭:天行健,君子以自强不息;地势坤,君子以厚德载物. 目录 前言 词法分析与语法分析的关系 工具介绍 flex的介绍 bison的介绍 flex的…

【云原生进阶之PaaS中间件】第一章Redis-2.2Redis IO模型

1 IO模型 linux系统也是一种应用,它是基于计算机硬件的一种操作系统软件。当我们接收一次网络传输,计算机硬件的网卡会从网络中将读到的字节流写到linux的buffer缓冲区内存中,然后用户空间会调用linux对外暴露的接口,将linux中的b…

将虚拟机dmesg日志内容通过串口输出到windows下文件中

将虚拟机dmesg日志内容通过串口输出到windows下文件中 文章目录 将虚拟机dmesg日志内容通过串口输出到windows下文件中a. 设置vmware添加serial port, 使用文件作为串口b. 启动ubuntu,修改/etc/default/grubc. ubuntu使用root用户登录d. 修改printk优先级&#xff0…

数据科学中使用的17 种相似性和相异性度量之欧氏距离

目录 1简介 2距离函数 2.1 L2范数(欧氏距离) 1简介 在数据科学中,相似性度量是一种衡量数据样本如何相互关联或相互接近的方法。另一方面,相异性度量是告诉数据对象有多少是不同的。此外,当相似的数据样本被分组到一…

异常检测专栏(一)异常检测概述

前言 异常检测一直是机器学习中一个活跃的研究领域,由于风险管理、合规、安全、将抗和医疗风险以及人工智能安全等广泛领域的需求和应用不断增加,异常检测发挥和越来越重要的总用。近年来,随着深度学习和计算机视觉技术的不断发展&#xff0c…

零死角玩转stm32中级篇4-ADC和DAC

本篇博文目录: 一.ADC的基础概念1.什么是ADC2.在单片机中我们一般使用ADC技术来做什么?3.怎么查看单片机的某一个引脚是否具有ADC功能4.ADC采集和引脚数据的读取有什么区别5.单片机内部采用的是数字信号,为什么还要采用ADC进行转换6.ADC的分类7.ADC的工作原理8.ADC…