【Java】基础入门 (十六)--- 异常

1.异常

1.1 异常概述

       异常是指程序在运行过程中出现的非正常的情况,如用户输入错误、除数为零、文件不存在、数组下标越界等。由于异常情况再程序运行过程中是难以避免的,一个良好的应用程序除了满足基本功能要求外,还应具备预见并处理可能发生的各种异常情况。因此,在开发中需要充分考虑各种意外情况,以提高程序的容错能力。异常处理事一种技术,用于处理这种异常情况。

       我们阅读下面的代码,通过这段代码来认识异常。 我们调用一个方法时,经常一不小心就出异常了,然后在控制台打印一些异常信息。其实打印的这些异常信息,就叫做异常。

public class ExceptionTest01 {
    public static void main(String[] args) {
        System.out.println(Integer.valueOf("abc"));
    }
}

       运行之后会出现如下的页面:

在这里插入图片描述

       因为在设计这个方法的时候,在方法中对调用者传递的参数进行校验,如果校验数据不合法,就会将异常信息封装成一个对象并抛出,JVM接收到异常对象之后,就把异常打印了。

public static Integer valueOf(String s) throws NumberFormatException {
	return Integer.valueOf(parseInt(s, 10));
}

       因为写代码时经常会出现问题,Java的设计者们早就为我们写好了很多个异常类,来描述不同场景下的问题。而有些类是有共性的所以就有了异常的继承体系。

1.1.1 异常的体系

在这里插入图片描述

所有异常类都是Throwable类的子类,它派生出两个子类, Error 类和 Exception 类:

       (1) Error 类:表示程序无法恢复的严重错误或者恢复起来比较麻烦的错误,例如内存溢出、动态链接失败、虚拟机错误等。应用程序不应该主动抛出这种类型的错误,通常由虚拟机自动抛出。如果出现这种错误,最好的处理方式是让程序安全退出。在进行程序设计时,我们更应关注Exception类。
       (2)Exception类:由Java应用程序抛出和处理的非严重错误,例如文件未找到、网络连接问题、算术错误(如除以零)、数组越界、加载不存在的类、对空对象进行操作、类型转换异常等。Exception类的不同子类对应不同类型的异常。Exception类又可分为两大类异常:

  • 不受检异常:也称为unchecked异常,包括RuntimeException及其所有子类。对这类异常并不要求强制进行处理,例如算术异常ArithmeticException等。
  • 受检异常:也称为checked异常,指除了不受检异常外,其他继承自Exception类的异常。对这类异常要求在代码中进行显式处理。

Java提供了多种异常类,下表列举了一些常见的异常类及其用途:

在这里插入图片描述

1.2 Java异常处理机制

1.2.1 异常处理

       Java的异常处理机制类似于人们对可能发生的意外情况进行预先处理的方式。在程序执行过程中,如果发生了异常,程序会按照预定的处理方式对异常进行处理。处理完异常之后,程序会继续执行。如果异常没有被处理,程序将会终止运行。

       Java的异常处理机制依靠以下 5 个关键字:trycatchfinallythrowthrows。这些关键字提供了两种异常处理方式。

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

  • try 块中包含可能会抛出异常的代码。
  • catch 块中用于捕获并处理指定类型的异常。
  • finally 块中的代码无论是否发生异常都会被执行,通常用于释放资源或清理操作。
package swp.kaifamiao.codes.Java.d0830;

/**
 * {class description}
 *
 * @author SWP
 * @version 1.0.0
 */
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");
    }
}

运行效果:

在这里插入图片描述

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

       ① 使用throws声明抛出异常

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

package swp.kaifamiao.codes.Java.d0830;

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

/**
 * {class description}
 *
 * @author SWP
 * @version 1.0.0
 */
public class Demo01 {
    public static void main(String[] args) {
        try {
            divide();
        }catch (InputMismatchException e){
            System.out.println("除数和被除数必须都是整数");
        }catch (ArithmeticException e){
            System.out.println("除数不能为零");
        }catch (Exception e){
            System.out.println("其他异常" + e.getMessage());
        }finally {
            System.out.println("感谢使用本程序");
        }
        System.out.println("程序结束");
    }


    /**
      通过throws声明抛出设计时异常
     */
    public 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("计算结束");
    }
}

       ②使用throw声明抛出异常

       除了系统自动抛出异常外,在编程过程中,有些问题是系统无法自动发现并解决的,如年龄不在正常范围之内,性别输入的不是“男”或“女”等,此时需要程序员而不是系统来自行抛出异常,把问题提交给调用者去解决。在Java语言中,可以使用throw关键字来自行抛出异常。

throw new Exception("message")
  • 如果 throw 语句抛出的异常是 Checked 异常,则该 throw 语句要么处于 try 块⾥,显式捕获该异常,要么放在⼀个带 throws 声明抛出的⽅法中,即把该异常交给该⽅法的调⽤者处理;
  • 如果 throw 语句抛出的异常是 Runtime 异常,则该语句⽆须放在 try 块⾥,也⽆须放在带 throws 声明抛出的⽅法中;程序既可以显式使⽤ try…catch来捕获并处理该异常,也可以完全不理会该异常,把该异常交给该⽅法调⽤者处理。

自行抛出Runtime 异常比自行抛出Checked 异常的灵活性更好。同样,抛出 Checked 异常则可以让编译器提醒程序员必须处理该异常。

1.2.2 自定义异常

       当JDK中的异常类型不能满足程序需求时,可以自定义异常类,使用自定义异常类一般有以下几个步骤:
       (1)定义异常类,并继承ExceptionRuntimeException
       (2)编写异常类的构造方法,向父类构造方法传入异常描述信息,并继承父类的其他实现方法;
       (3)实例化自定义异常对象,并在程序中使用throw抛出。

举例:实现以下需求

需求:写一个saveAge(int age)方法,在方法中对参数age进行判断,如果age<0或者>=150就认为年龄不
合法,如果年龄不合法,就给调用者抛出一个年龄非法异常。

分析:Java的API中是没有年龄非常这个异常的,所以我们可以自定义一个异常类,用来表示年龄非法异常,然后再方法中抛出自定义异常即可。


自定义一个AgeIllegalException异常类:

package swp.kaifamiao.codes.Java.d0830;

/**
 * {class description}
 * 自定义异常类 AgeIllegalException
 * 继承 Exception 类
 * 用于表示年龄不合法的异常
 * @author SWP
 * @version 1.0.0
 */
public class AgeIllegalException extends Exception {
    public AgeIllegalException() {
    }

    public AgeIllegalException(String message) {
        super(message);
    }
}
package swp.kaifamiao.codes.Java.d0830;

/**
 * {class description}
 * 异常测试类 ExceptionTest
 * 用于测试自定义异常 AgeIllegalException
 * 当年龄不合法时抛出 AgeIllegalException 异常
 * 并在 main 方法中捕获并处理该异常
 * @author SWP
 * @version 1.0.0
 */
public class ExceptionTest {
    public static void main(String[] args) {
        try {
            saveAge(225);
            System.out.println("saveAge2底层执行是成功的!");
        } catch (AgeIllegalException e) {
            e.printStackTrace();
            System.out.println("saveAge2底层执行是出现bug的!");
        }
    }

    // 在方法中对age进行判断,不合法则抛出AgeIllegalException

    public static void saveAge(int age) throws AgeIllegalException {
        if (age > 0 && age < 150) {
            System.out.println("年龄被成功保存: " + age);
        } else {
            // 用一个异常对象封装这个问题
            // throw 抛出去这个异常对象
            throw new AgeIllegalException("age is illegal, your age is " + age);
        }
    }
}

运行效果:

在这里插入图片描述


1.2.3 异常链

异常链(Exception Chaining)是指在异常处理过程中,将当前的异常作为原因(cause)链接到另一个异常上。通过异常链,可以追踪异常发生的完整路径,并提供更多的上下文信息。

(1)定义testOne,testTwo,testThree方法,testTwo对testOne抛出的异常进行捕获,testThree对testTwo抛出的异常进行捕获:

package swp.kaifamiao.codes.Java.d0830;

/**
 * {class description}
 *
 * @author SWP
 * @version 1.0.0
 */
public class TryDemoFive {
    public static void main(String[] args) {
        try {
            testThree();
        } catch (Exception e) {
            // 打印完整的异常信息
            e.printStackTrace();
        }
    }

    public static void testOne() throws MyException {
        throw new MyException("我是一个异常");
    }

    public static void testTwo() throws Exception {
        try {
            testOne();
        } catch (Exception e) {
            // 在新抛出的异常中添加原来的异常信息
            throw new Exception("我是新产生的异常1", e);
        }
    }

    public static void testThree() throws Exception {
        try {
            testTwo();
        } catch (Exception e) {
            // 在要抛出的对象中使用 initCause() 方法,添加上一个产生异常的信息
            Exception e2 = new Exception("我是新产生的异常2");
            e2.initCause(e);
            throw e2;
        }
    }
}

(2)定义MyException 类:

package swp.kaifamiao.codes.Java.d0830;

/**
 * {class description}
 *
 * @author SWP
 * @version 1.0.0
 */
public class MyException extends Exception{
    public MyException(String message) {
        super(message);
    }
}

(3)运行效果:

在这里插入图片描述

2.思考

2.1 什么是异常?

	异常是指程序在运行过程中出现的非正常的情况,如用户输入错误、除数为零、文件不存在、数组下标越界等。

2.2 什么是运行时异常?

运行时异常(Runtime Exception)是指在程序运行期间可能抛出的异常,它们属于非受检异常(Unchecked Exception)。与受检异常(Checked Exception)相比,运行时异常在编译期不需要强制处理或声明。

运行时异常通常表示程序的逻辑错误或者错误的使用方式,例如数组越界、空指针引用等。这些异常通常是由程序员编码时的错误导致的,但在编译时却无法确定是否会发生异常。

2.3 如何处理异常?

(1) 使用try、catch、finally来捕获和处理异常;
(2) 使用throw、throws 来抛出异常

2.4 什么是checked异常?什么是unchecked异常?

(1) 受检异常是在编译时强制要求处理的异常,需要使用 try-catch 块捕获并处理,或者在方法签名中使用 throws 关键字声明异常。
(2) 非受检异常是由程序逻辑错误或错误的使用方式引起的异常,在编译时不需要强制要求处理,但仍可以选择性地进行捕获和处理。

2.5 构造方法可以throws异常吗?对子类有影响吗?有什么影响?

可以在构造方法中抛出异常,与其他方法一样,构造方法也可以声明受检异常并通过 throws 关键字将其抛出。
如果在父类的构造方法中声明了受检异常,那么所有继承自该类的子类构造方法必须显示地处理这些异常或者在它们的方法签名中使用 throws 关键字将其抛出。否则编译会报错。

2.6 throw和throws的区别?

(1) 作⽤不同:throw⽤于程序员⾃⾏产⽣并抛出异常,throws⽤于声明该⽅法内抛出了异常。
(2) 使⽤位置不同:throw位于⽅法体内部,可以作为单独的语句使⽤;throws必须跟在⽅法参数列表的后⾯,不能单独使⽤。
(3) 内容不同:throw抛出⼀个异常对象,只能是⼀个;throws后⾯跟异常类,可以跟多个。

2.7 能否自己throw一个Error?

可以使用 throw 关键字抛出一个 Error 对象。在Java中,Error 是 Throwable 类的子类,它表示严重的错误和异常情况,通常由Java虚拟机(JVM)或底层系统引起,例如 OutOfMemoryError、StackOverflowError 等。

与 Exception 不同,Error 通常表示不可恢复的错误或系统级故障,它们是无法预料和处理的,一般不建议程序员捕获和处理 Error。通常情况下,Error 会导致程序中止执行。

以下是一个示例,演示如何抛出一个 Error:

public class Example {
    public static void main(String[] args) {
        throw new Error("This is an error.");
    }
}

需要注意的是,抛出 Error 可能会导致程序异常终止,并且不应该被常规的异常处理机制所捕获和处理。因此,在编写代码时,通常不建议自己抛出 Error,除非确实具有特殊的需求或深入了解它们的影响。一般的异常处理应该针对 Exception 及其子类。

2.8 假如throw里面有return语句,catch里面有return语句,finally里面也有return语句,为什么最后返回的是finally里面的return语句?

在 Java 中,finally 块中的 return 语句会覆盖之前的 try 或 catch 块中的 return 语句,并决定最终的返回值。这是因为无论在 try、catch 或者 finally 块中执行了哪个 return 语句,都会直接结束整个方法并返回对应的值。

根据 Java 语言规范,finally 块中的 return 语句会在方法返回之前执行,以确保在方法返回之前可以进行一些必要的清理工作。所以,在 finally 块中使用 return 语句将决定最终的返回值。

2.9 为啥要自定义异常?如何自定义异常?

当JDK中的异常类型不能满足程序需求时,可以自定义异常类,自定义异常在编程中非常有用,它能够提供更加准确和具体的异常信息,并能够满足特定业务需求。通过自定义异常,可以将代码中可能发生的异常情况进行分类和处理,使代码更加清晰、可读性更高,并且有助于调试和错误处理。
(1)定义异常类,并继承`Exception` 或`RuntimeException`;
(2)编写异常类的构造方法,向父类构造方法传入异常描述信息,并继承父类的其他实现方法;
(3)实例化自定义异常对象,并在程序中使用throw抛出。

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

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

相关文章

实验室的服务器和本地pycharm怎么做图传

参考 远程调试 qt.qpa.xcb: could not connect to display, echo DISPLAY为空[已解决]_功夫小象的博客-CSDN博客 先安装x11 MobaXterm x11-forwarding_C--G的博客-CSDN博客 我是在容器中搞得 1&#xff0c;安装qt5 pip install PyQt5 -i https://pypi.douban.com/simple …

Spring-SpringBoot-SpringMVC-MyBatis常见面试题

文章目录 Spring篇springbean是安全的的?什么是AOP你们工作中有用过AOP吗spring中的事务是如何实现的spring中事务失效场景Spring的生命周期spring中的循坏依赖springMVC的执行流程springboot的启动原理常用注解MyBatis执行流程Mybatis是否支持延迟加载&#xff1f;Mybatis的一…

静态类方法的同步

由于在调用静态方法时&#xff0c;对象实例不一定被创建。因此&#xff0c;就不能使用this来同步静态方法&#xff0c;而必须使用Class对象来同步静态方法。代码如下&#xff1a; 通过synchronized块同步静态方法 public class StaticSyncBlock { public static void…

ETC reset

ETC重新激活 换前挡风玻璃膜会把ETC设备拿下来&#xff0c;需要到【ETC服务中心】重新【粘上去】&#xff0c;另外需要工作人员用手持终端【重新激活】 ETC 背面有个 【白色】开关小柱子&#xff0c;一旦拆下来就失效&#xff0c;因为这个开关弹出来了 截面图看就是这样的&…

动态不确定性的动态S过程(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

2023年高教社杯 国赛数学建模思路 - 案例:感知机原理剖析及实现

文章目录 1 感知机的直观理解2 感知机的数学角度3 代码实现 4 建模资料 # 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 1 感知机的直观理解 感知机应该属于机器学习算法中最简单的一种算法&#xff0c;其…

【项目 计网7】4.20 多进程实现并发服务器 4.22 多线程实现并发服务器

文章目录 4.20 多进程实现并发服务器server_process.cclient.c4.22 多线程实现并发服务器客户端代码&#xff1a;服务端代码&#xff1a; 4.20 多进程实现并发服务器 要实现TCP通信服务器处理并发的任务&#xff0c;使用多线程或者多进程来解决。 思路&#xff1a; 1、一个父进…

打开软件报错mfc100u.dll缺失是什么意思?简单式修复mfc100u.dll问题

首先&#xff0c;我们需要了解什么是MFC100U.dll文件以及它的作用。MFC100U.dll是一个Microsoft Foundation Class (MFC)库文件&#xff0c;它是Visual C应用程序开发的一部分。MFC库提供了许多通用的功能&#xff0c;如窗口管理、消息处理等&#xff0c;可以帮助开发者更快速地…

成集云 | 抖店客户静默下单催付数据同步钉钉 | 解决方案

源系统成集云目标系统 方案介绍 随着各品牌全渠道铺货&#xff0c;主播在平台上直播时客户下了订单后不能及时付款&#xff0c;第一时间客户收不到提醒&#xff0c;不仅造成了客户付款率下降&#xff0c;更大量消耗了企业的人力成本和经济。而成集云与钉钉深度合作&#xff0…

【力扣】55、跳跃游戏

var canJump function(nums){let cover 0;for(let i0;i<nums.length;i){if(i<cover){cover Math.max(nums[i]i,cover);if(cover >nums.length-1){return true;}}}}

【状压+概率DP】CF678 E

Problem - E - Codeforces 题意&#xff1a; 思路&#xff1a; 首先&#xff0c;n < 18&#xff0c;应当想到状压 很明显&#xff0c;这里可以使用状压DP 设 dp[s][i] 表示&#xff0c;现在选的方案为 s &#xff0c;且我是 i 的最终胜利的概率是多少 重要的是转移 这是…

SpringBoot+MyBatisPlus+MySql+vue2+elementUi的案例、java访问数据库服务、java提供接口服务

文章目录 前言后端关键代码前端关键代码完整代码 前言 1、项目不使用前后端分离。 2、在创建SpringBoot的时候要注意各个插件间的版本问题。 3、后端技术SpringBootMyBatisPlusMySql。 4、前端技术vue2elementUi。 后端关键代码 简单介绍 1、数据库名称ssm_db 2、表名称tbl_bo…

火热的大模型AIGC对数据中心存储趋势有什么影响?

随着人工智能和大数据技术的不断发展&#xff0c;业内AIGC&#xff08;人工智能、图形处理和云计算&#xff09;和大模型的发展趋势正在对数据中心存储发展方向产生深远的影响&#xff0c;主要集中对数据量和高性能计算的诉求。 大模型的普及要求数据中心存储具备更大的容量。大…

【模拟】算法实战

文章目录 一、算法原理二、算法实战1. leetcode1576 替换所有的问号2. leetcode495 提莫攻击3. leetcode6 N字形变换4. leetcode38 外观数列5. leetcode1419 数青蛙 三、总结 一、算法原理 模拟就是用计算机来模拟题目中要求的操作&#xff0c;模拟题目通常具有代码量大、操作…

域名信息收集

作用 1.爆破 2.查询资产漏洞 域名联系人信息 1.whois.chinaz.com 2.whois.cnnic.cn/WelcomeServlet 3.kali whois 工具 4.mwhois.chinaz.com 5.http://whois.chinaz.com/reverse 域名反查 6.beian.miit.gov.cn/#/Integrated/index 国家备案系统 7.beian88.com 8.天眼查查询企…

机器学习技术(六)——有监督学习算法之线性回归算法实操

机器学习技术&#xff08;五&#xff09;——有监督学习之线性回归算法实操 引言&#xff1a; 机器学习监督算法是一种基于已有标记数据的学习方法&#xff0c;通过对已知输入和输出数据的学习&#xff0c;建立一个模型来预测新的输入数据的输出。这种算法模仿人类的学习过程&a…

39、springboot的前端静态资源的WebJar支持(bootstrap、jquery等)及自定义图标和首页

★ WebJar支持 Spring Boot支持加载WebJar包中的静态资源&#xff08;图片、JS、CSS&#xff09;&#xff0c; WebJar包中的静态资源都会映射到/webjars/**路径。——这种方式下&#xff0c;完全不需要将静态资源复制到应用的静态资源目录下。只要添加webjar即可。假如在应用的…

生态经济学领域里的R语言机器学(数据的收集与清洗、综合建模评价、数据的分析与可视化、数据的空间效应、因果推断等)

近年来&#xff0c;人工智能领域已经取得突破性进展&#xff0c;对经济社会各个领域都产生了重大影响&#xff0c;结合了统计学、数据科学和计算机科学的机器学习是人工智能的主流方向之一&#xff0c;目前也在飞快的融入计量经济学研究。表面上机器学习通常使用大数据&#xf…

4.5 TCP优化

TCP 三次握手的性能提升 三次握手的过程在一个 HTTP 请求的平均时间占比 10% 以上&#xff0c;所以要正确使用三次握手的中参数&#xff0c;需要先用netstat命令查看是哪个握手阶段出了问题&#xff0c;主动发起连接的客户端优化相对简单些&#xff0c;而服务端需要监听端口&a…

leetcode 42. 接雨水

2023.8.29 本题可以用双指针做&#xff0c;求出每一列能盛的雨水&#xff0c;再相加即可。不过暴力法会超时&#xff0c;需要优化。 双指针&#xff08;暴力&#xff09;&#xff1a; class Solution { public:int trap(vector<int>& height) {int ans 0;for(int …