异常的捕获和处理

news2025/1/21 4:52:10

目录

一、异常

1.异常概述

1.1认识异常

1.2Java异常体系结构

2.Java异常处理机制

2.1异常处理

2.2捕获异常

2.2.1使用try-catch捕获异常

2.2.2使用try-catch-finally处理异常

2.2.3使用多重catch处理异常

2.3抛出异常

2.3.1使用throws声明抛出异常

2.3.2使用throw抛出异常

2.4自定义异常

2.5异常链


一、异常

1.异常概述

1.1认识异常

异常是指程序在运行过程中出现的非正常情况。

public class Main {

    public static void main(String[] args) {
        int i=1,j=0,res;
        System.out.println("begin");
        res=i/j;//算术运算异常
        System.out.println("end");
    }

}

一旦程序发生异常将会立即结束,因此“end”没有输出。

1.2Java异常体系结构

异常在Java中被封装成了各种异常类。

程序中常见的异常: 

Exception设计时异常异常层次结构的根类
IOException设计时异常IO异常的根类,属于非运行时异常
FileNotFoundException设计时异常文件操作时,找不到文件
RuntimeException运行时异常运行时异常的根类,RuntimeException及其子类,不要求必须处理
ArithmeticException运行时异常算术运算异常
lllegalArgumentException运行时异常方法接收到非法参数
ArrayIndexOutOfBoundsException运行时异常数组越界访问异常
NullPointerException运行时异常尝试访问null对象的成员时发生的空指针异常
ArrayStoreException运行时异常数据存储异常,写数组操作时,对象或数据类型不兼容
ClassCastException运行时异常类型转换异常
IIIegalThreadStateException运行时异常试图非法改变线程状态,例如试图启动一个已经运行的线程
NumberFormatException运行时异常数据格式异常,试图把一字符串非法转换成数值

2.Java异常处理机制

2.1异常处理

Java中的异常处理机制依靠5个关键字:try、catch、finally、throw、throws。这些关键字提供了两种异常处理方式:

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

try块中包含可能会抛出异常的代码

catch块中用户捕获和处理指定类型的异常

finally块中的代码无论是否发生异常都会被执行,通常用于释放资源或清理操作

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

throw关键字用于手动抛出异常对象。

throws关键字用于在方法声明中指定可能抛出的异常类型,表示该方法可能会抛出该类型的异常,由调用者来处理。

2.2捕获异常
2.2.1使用try-catch捕获异常
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 (Exception e){
            System.out.println("caught");
            e.printStackTrace();
        }
        System.out.println("over");
    }

}
  • 如果try语句块中的所有语句正常执行完毕,没有发生异常,那么catch语句块中的所有语句将被忽略。
  • 如果try语句块在执行过程中发生异常,并且这个异常与catch语句块中声明的异常类型匹配,那么try语句块中剩下的代码都将被忽略,相应的catch语句块将会被执行。匹配是指catch中所处理的异常类型与try中发生的异常类型完全一致或者是它的父类。
  • 如果try语句块在执行过程中发生异常,而抛出的异常在catch语句块中没有被声明,那么程序立即终止运行,程序被强迫退出。
  • catch语句块中可以加入用戶自定义处理信息,也可以调用异常对象的方法输出异常信息,常用的方法如下:
    void prinStackTrace() :输出异常的堆栈信息。堆栈信息包括程序运行到当前类的执行流程,它将输出从方法调用处到异常抛出处的方法调用的栈序列。
    String getMessage() :返回异常信息描述字符串,该字符串描述了异常产生的原因,是 printStackTrace() 输出信息的一部分。
2.2.2使用try-catch-finally处理异常

无论try块中是否发生异常,finally语句块中的代码总能被执行。

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");
    }

}
  • 如果try语句块中所有语句正常执行完毕,程序不会进入catch语句块执行,但是finally语句块会被执行。 
  • 如果try语句块在执行过程中发生异常,程序会进入到catch语句块捕获异常, finally语句块也会被执行。
  • try-catch-finally结构中try语句块是必须存在的,catch、finally语句块为可选,但两者至少出现其中之一。

即使在catch语句块中存在return语句,finally语句块中的语句也会执行。发生异常时的执行顺序是,先执行catch语句块中return之前的语句,再执行finally语句块中的语句,最后执行catch语句块中的return语句退出。

finally语句块中语句不执行的唯一情况是在异常处理代码中执行了 System.exit(1) ,退出Java虚拟机。

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();
            System.exit(1);
        }finally {
            System.out.println("finally");
        }
        System.out.println("over");
    }

}

public class Main {

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

    private static int method() {
        int i=1;
        try {
            i++;//2
            System.out.println("try block,i="+i);//try block,i=2
            return i;//2
        }catch (Exception e){
            i++;
            System.out.println("catch block,i="+i);
        }finally {
            i=10;
            System.out.println("finally block,i="+i);//finally block,i=10
        }
        return i;
    }
}

 

public class Main {

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

    private static int method() {
        int i=1;
        try {
            i++;
            System.out.println("try block,i="+i);//try block,i=2
            return i;
        }catch (Exception e){
            i++;
            System.out.println("catch block,i="+i);
            return i;
        }finally {
            i=10;
            System.out.println("finally block,i="+i);//finally block,i=10
            return i;//10
        }
    }
}

2.2.3使用多重catch处理异常

catch语句块的排列顺序必须是从子类到父类,最后一个一般是Exception类。这是因为在异常处理中,catch语句块会按照从上到下的顺序进行匹配,系统会检测每个catch语句块处理的异常类型,并执行第一个与异常类型匹配的catch语句块。如果将父类异常放在前面,子类异常的catch语句块将永远不会被执行,因为父类异常的catch语句块已经处理了异常。

一旦系统执行了与异常类型匹配的catch语句块,并执行其中的一条catch语句后,其后的catch语句块将被忽略,程序将继续执行紧随catch语句块的代码。 

子类异常应该放在前面,父类异常应该放在后面。 

import java.util.InputMismatchException;
import java.util.Scanner;

public class Main {

    public static void main(String[] args) {
        Scanner input=new Scanner(System.in);
        try {
            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("计算结束");
        }catch (InputMismatchException e){
            System.out.println("除数和被除数都必须是整数!");
        }catch (ArithmeticException e){
            System.out.println("除数不能为0!");
        }catch (Exception e){
            System.out.println("其他异常"+e.getMessage());
        }finally {
            System.out.println("感谢使用本程序!");
        }
        System.out.println("程序结束!");
    }


}

第一种:被除数发生异常

 

 第二种:除数发生异常

第三种:除数为0

2.3抛出异常
2.3.1使用throws声明抛出异常

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

import java.util.InputMismatchException;
import java.util.Scanner;

public class Main {

    public static void main(String[] args) {
        try {
            divide();
        }catch (InputMismatchException e){
            System.out.println("除数和被除数都必须是整数!");
        }catch (ArithmeticException e){
            System.out.println("除数不能为0!");
        }catch (Exception e){
            System.out.println("其他异常"+e.getMessage());
        }finally {
            System.out.println("感谢使用本程序!");
        }
        System.out.println("程序结束!");
    }
    private 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("计算结束");
    }

}
2.3.2使用throw抛出异常

在Java语言中,可以使用throw关键字来自行抛出异常。

package structure;

public class Main {
    public static void main(String[] args) {
        Person1 person=new Person1();
        try {
            person.setName("扈三娘");
            person.setAge(18);
            person.setGender("男女");
            person.print();
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}
class Person1{
    private String name="";
    private int age=0;
    private String gender="男";

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) throws Exception{
        if ("男".equals(gender)||"女".equals(gender)){
            this.gender = gender;
        }else {
            throw new Exception("性别必须是男或女!");
        }

    }
    public void print(){
        System.out.println("姓名:"+this.name+"性别:"+this.gender+"年龄:"+this.age);
    }
}

  • 如果 throw 语句抛出的异常是 Checked 异常,则该 throw 语句要么处于 try 块里,显式捕获该异常,要么放在一个带 throws 声明抛出的方法中,即把该异常交给该方法的调用者处理; 
  • 如果 throw 语句抛出的异常是 Runtime 异常,则该语句无须放在 try 块里,也无须放在带 throws 声明抛出的方法中;程序既可以显式使用 try...catch来捕获并处理该异常,也可以完全不理会该异常,把该异常交给该方法调用者处理。
  • 自行抛出Runtime 异常比自行抛出Checked 异常的灵活性更好。同样,抛出 Checked 异常则可以让编译器提醒程序员必须处理该异常。

 throw和throws的区别:

1.作用不同:throw用于程序员自行产生并抛出异常,throws用于声明该方法内抛出了异常。
2.使用位置不同:throw位于方法体内部,可以作为单独的语句使用;throws必须跟在方法参数列表的后面,不能单独使用。
3.内容不同:throw抛出一个异常对象,只能是一个;throws后面跟异常类,可以跟多个。

2.4自定义异常

当JDK中的异常类型不能满足程序的需要时,可以自定义异常类。步骤:

①定义异常类,并继承Exception或者RuntimeException。

②编写异常类的构造方法,向父类构造方法传入异常描述信息,并继承父类的其他实现方法。

③实例化自定义异常对象,并在程序中使用throw抛出。

package structure;

public class Main {
    public static void main(String[] args) {
        Person1 person=new Person1();
        try {
            person.setName("扈三娘");
            person.setAge(18);
            person.setGender("男女");
            person.print();
        }catch (GenderException e){
            e.printStackTrace();
        }
    }
}
//自定义异常类
class GenderException extends Exception{
    public GenderException(String message){
        super(message);
    }
}
class Person1{
    private String name="";
    private int age=0;
    private String gender="男";

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) throws GenderException{
        if ("男".equals(gender)||"女".equals(gender)){
            this.gender = gender;
        }else {
            throw new GenderException("性别必须是男或女!");
        }

    }
    public void print(){
        System.out.println("姓名:"+this.name+"性别:"+this.gender+"年龄:"+this.age);
    }
}

自定义异常可能是编译时异常,也可能是运行时异常 。

1.如果自定义异常类继承Excpetion,则是编译时异常。
特点:方法中抛出的是编译时异常,必须在方法上使用throws声明,强制调用者处理。
2.如果自定义异常类继承RuntimeException,则运行时异常。
特点:方法中抛出的是运行时异常,不需要在方法上用throws声明。

2.5异常链

有时候我们会捕获一个异常后再抛出另一个异常。

顾名思义就是将异常发生的原因一个传一个串起来,即把底层的异常信息传给上层,这样逐层抛出。

在要抛出的对象中使用 initCause() 方法,添加上一个产生异常的信息; getCause() 可以获取当前异常对象的上一个异常对象。

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

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

相关文章

小企业需不需要内部知识库?为什么都在倡导内部知识沉淀?

有多种方法可以提高员工敬业度和员工工作效率,从给予信任到创造积极的工作环境。但一还有一个不为人知但十分有效的方式——为员工创建良好的内部知识库。所以小企业同样需要内部知识库,以下是为什么倡导内部知识沉淀的理由: 知识积累与传承…

Http 1.0 1.1 2.0 3.0 版本差别

Http 1.0 发布年份:1996 非官方标准 短链接:每一次请求都对应一次TCP的连接与释放 开销大:每次请求都要TCP的连接与释放队头阻塞:每次请求都必须等上一次请求获得响应之后,才可以发送;效率低下 缓存&…

理论转换实践之keepalived+nginx实现HA

背景: keepalivednginx实现ha是网站和应用服务器常用的方法,之前项目中单独用nginx实现过负载均衡和服务转发,keepalived一直停留在理论节点,加之最近工作编写的一个技术文档用到keepalived,于是便有了下文。 服务组件…

Linux系统编程:线程同步及生产与消费者模型

目录 一. 线程同步的概念及功能 二. 线程同步的实现方法 2.1 条件变量相关函数 2.2 线程同步demo代码 三. 生成与消费者模型 3.1 生产与消费者模型的概念 3.2 生产与消费者模型实现代码 四. 总结 一. 线程同步的概念及功能 为了了解线程同步的概念及实现的功能&#xf…

Revit SDK:PointCurveCreation 创建点来拟合曲线

前言 这个例子通过留个例子来展示如何通过点来拟合曲线或者曲面。 内容 PointsParabola 生成抛物线的核心逻辑&#xff1a; double yctr 0; XYZ xyz null; ReferencePoint rp null; double power 1.2; while (power < 1.5){double xctr 0;double zctr 0;while (…

数据集学习笔记(七):不同任务数据集的标签介绍(包含目标检测、图像分割、行为分析)

文章目录 一、目标检测1.1 TXT1.2 COCO1.3 XML 二、图像分割2.1 json2.1 TXT2.1.1 json转txt 三、行为分析3.1 TXT3.2 JSON 一、目标检测 1.1 TXT 每行表示&#xff08;类别&#xff0c;中心x相对坐标&#xff0c;中心y相对坐标&#xff0c;相对宽度、相对高度&#xff09; 1…

FFmpeg4.3.1+h264在windows下编译与VS2017项目集成

前言 在Android音视频开发中&#xff0c;网上知识点过于零碎&#xff0c;自学起来难度非常大&#xff0c;不过音视频大牛Jhuster提出了《Android 音视频从入门到提高 - 任务列表》&#xff0c;结合我自己的工作学习经历&#xff0c;我准备写一个音视频系列blog。本文是音视频系…

python spyder环境配置

首先安装python&#xff0c;配置环境变量等等 其次 pip install spyder 安装 spyder 最后启动 spyder&#xff0c;cmd下 执行 spyder&#xff0c;就打开了 调试下面的代码看看是否是系统的python import sys print(sys.executable) print(sys.path) 工具-偏好-python调试器 …

QT(8.30)常用类与组件,实现登录界面

1.作业&#xff1a; 完成一个登录界面(图片未附带): 头文件: #ifndef WIDGET_H #define WIDGET_H#include <QWidget>#include <QLineEdit>//行编辑器#include<QIcon>//图标#include<QLabel>//标签#include<QPushButton>//按钮#include<QIc…

【pyqt5界面化工具开发-13】QtDesigner功能择优使用

目录 0x00 前言&#xff1a; 一、完成基本的布局 二、其他功能的使用 三、在代码行开发 0x00 前言&#xff1a; QtDesigner工具的择优使用&#xff1a; 1、他的界面开发&#xff0c;是我们主要需要使用的功能 2、他的其他功能的使用&#xff0c;有需要就可使用&#xff…

报This application has no explicit mapping for /error 解决方法

Application启动类的位置不对&#xff0c;要将Application类放在最外侧&#xff0c;即包含所有子包。 没发现这个问题&#xff0c;卡了我老半天&#xff0c;兄弟们可以看一下你们是不是这个问题。

万人在线,一站式自动化运维 SysOM 3.0重磅发布!龙蜥社区系统运维 MeetUp 回顾来了

8 月 12 日&#xff0c;由龙蜥社区系统运维 SIG 主办&#xff0c;乘云数字协办的&#xff0c;主题为“观测&#xff0c;让运维更简单&#xff01;”的系统运维 MeetUp 于杭州圆满结束。来自乘云数字、谐云科技、乐维、云杉网络、擎创科技、观测云、阿里云以及浙江大学等众多厂商…

基于爬行动物算法优化的BP神经网络(预测应用) - 附代码

基于爬行动物算法优化的BP神经网络&#xff08;预测应用&#xff09; - 附代码 文章目录 基于爬行动物算法优化的BP神经网络&#xff08;预测应用&#xff09; - 附代码1.数据介绍2.爬行动物优化BP神经网络2.1 BP神经网络参数设置2.2 爬行动物算法应用 4.测试结果&#xff1a;5…

vue3批量导出文件,打包成压缩包

1.下载插件 npm install jszip npm install file-saver2.封装方法 新建一个exportFileZip.js文件 // 引入实现下载压缩包的两个库 import JSZip from jszip; import FileSaver from file-saver; // 引入请求模块 import axios from axios // 实现下载压缩包按钮的方法 fileA…

kotlin实现猜数游戏

游戏规则 1.程序随机生成一个1到100的数字&#xff0c;作为MagicNumber 2.用户根据提示输入数据&#xff0c;只有三次机会输入数据 代码 代码很简单&#xff0c;使用了let内置函数 fun main() {//生成随机数可以使用java的方法//val magicNumber Random().nextInt(11)val ma…

GiraffeDet助力yolov8暴涨分---有可执行源码

Yolov8魔改–加入GiraffeDet模型提高小目标效果 VX搜索晓理紫关注并回复有yolov8-GiraffeDet获取代码 [晓理紫] 1 GiraffeDet模型 GiraffeDet是一种新颖的粗颈范例&#xff0c;一种类似长颈鹿的网络&#xff0c;用于高效的目标检测。 GiraffeDet 使用极其轻量的主干和非常深且…

助力网络管理的利器:企业办公网络中的VLAN划分策略

企业办公网络的性能和安全性对员工的高效工作和信息安全具有重要意义。在实现这一目标时&#xff0c;VLAN&#xff08;Virtual Local Area Network&#xff09;划分在网络设计中发挥着至关重要的作用。通过将办公网络划分为多个虚拟局域网&#xff0c;VLAN划分可以实现网络资源…

【论文精读】Swin Transformer: Hierarchical Vision Transformer using Shifted Windows

Swin Transformer: Hierarchical Vision Transformer using Shifted Windows 前言Abstract1. Introduction2. Related Work3. Method3.1. Overall Architecture3.2. Shifted Window based Self-AttentionSelf-attention in non-overlapped windowsShifted window partitioning …

streamlit-高级功能

缓存 st.cache_data st.cache_resource 为应用程序添加会话状态 会话状态 会话状态应用到应用程序 会话状态和小部件关联 可序列化会话状态 注意事项和限制 命令行选项 应用程序菜单 菜单选项 开发者选项 streamlit配置 按钮行为和示例 连接到数据 数据框 形式 小部件语义 …

pycharm 打开Terminal时报错activate.ps1,因为在此系统上禁止运行脚本,并因此无法进入虚拟环境

pycharm 打开Terminal时报错activate.ps1&#xff0c;因为在此系统上禁止运行脚本&#xff0c;并因此无法进入虚拟环境 如下图所示&#xff1a; 网上说可以set_restrictFalse什么的&#xff0c;虽然也可但可能会降低电脑安全性&#xff0c;可以将下面的终端改为cmd.exe即可