异常详解

🦔异常

发现错误的理想时机是在编译阶段,也就是在运行程序之前。然而编译期间并不能找到所有的错误,余下的问题必须在运行期间解决。这就需要错误源能够通过某种方式,把适当的信息传递给某个接受者——该接受者知道如何正确处理这个问题。
​ Java编程思想(第四版)

概念

异常指不期而至的各种状况,如除0操作、用户输入不合法、内存溢出、读取文件不存在等等情况。

Java异常是一个描述在代码段中发生异常的对象,当发生异常时,一个代表该异常的对象被创建并且在导致该异常的方法中被抛出,而该方法可以选择自己处理或者传递该异常。

使用异常不仅降低了处理错误代码的复杂度,并且使代码变得更加健壮。

异常的体系结构

Java把异常当作对象来处理,并定义一个基类 java.lang.Throwable作为所有异常的超类。

Java异常层次结构图:

异常详解

在Java API中已经定义了许多异常类,这些异常类分为两大类, 错误 Error 和异常 Exception

  • Error Java虚拟机无法解决的严重问题,如:JVM内部错误,资源耗尽等情况。一般不编写针对性的代码进行处理。
  • Exception 因为其他编程错误或偶然的外在因素导致的一般性问题,如:控制针访问、视图读取不存在的文件、网络连接中断、数组索引越界等情况。可以编写针对性的代码进行处理。

遇到这些异常情况有两种解决办法:一种时抛出异常,一种是捕获异常。

如果我们遇见异常,解决是最好的,不能解决交由上层环境,如果上层环境还是不能解决,继续向上抛,直到main()方法将异常抛给JVM,JVM将使用默认的异常处理程序:终止程序,打印异常信息

捕获异常的最佳时机是在编译期间,但有些异常是在运行期间才会发生的,如:除0操作、数组索引越界

所以,Exception又分为

  • 编译时异常(受检异常) 是指编译器要求必须处理的异常,是程序在运行期间由于外界因素导致的一般性错误。如果不进行处理,可能导致意想不到的结果。一般编译器会进行提示。如:IOException、SQLException、ClassException
  • 运行时异常 编译不要求强制处理的异常,一般是在编程过程中的逻辑错误,可以不做处理。因为这类异常非常普遍,如进行全局处理,会影响程序的可读性以及运行效率。程序员应该积极避免这类异常。对于这类异常,或者叫Bug进行try…catch处理是毫无意义的。java规定,运行时异常将由运行时系统自动抛出,允许应用程序忽略运行时异常

除了RuntimeException和Error其余都是受检异常,会在编译期间检测异常

常见异常

  • ArrayIndexOutOfBoundsException
int[] array = {1,2,3,4,5};
for (int i = 0; i < 6; i++) {
    System.out.println(array[i] + "");
}
  • NUllPointException
int[] array = {1,2,3};
array = null;
for (int i = 0; i < array.length; i++) {
    System.out.println(array[1]);
}
  • ArithmeticException
int x = 0;
int y = 3 / x;
System.out.println(y);
  • ClassCastException
Object date = new Date();
CommonException exception = new CommonException();
exception = (CommonException) date;

异常处理机制

1)抛出异常

对于在当前环境中没办法获得更多信息去处理这个异常,或者在当前环境中处理异常没有意义的时候,我们需要把这个异常抛出这个环境,交由上层方法调用者去处理。

抛出异常后,会有几件事情发生:

  1. 使用new在堆上创建一个异常对象。
  2. 终止当前的执行路径,并且在当前环境中弹出对异常对象的引用,只要异常被捕获,根据这个异常对象的引用,就能控制程序的指向。
  3. 异常处理机制接管程序,并寻找一个恰当的地方(异常处理程序或异常处理器),继续执行程序,它的任务是将程序从错误状态中恢复,使程序要么换种方法运行,要么继续运行下去。

2)捕获异常

在方法抛出异常后,系统转而寻找合适的异常处理器。潜在的异常处理器是异常发生时依次存留在调用栈中的方法的集合。当方法抛出的异常类型和异常处理器所能处理的异常类型相符,或是异常处理器处理异常类型的子类时,达到匹配。运行时系统从发生异常的方法开始,依次回查调用栈中的方法,直到找到含有合适异常处理器的方法执行,当运行时系统遍历调用栈而未找到合适的异常处理器的时候,则运行时系统终止,即Java程序终止

异常处理语法

1)try…catch

try代码块中的区域是监控区域,当try代码块中的代码出现异常的时候,自动抛出异常,创建异常对象

catch代码块用于捕获异常,执行异常程序,catch中的代码将保证程序正常运行下去

一个语句中产生多种异常时,这时需要多重catch语句,排列规则是:先小后大,先子类再父类,否则捕获底层异常的catch子句会被屏蔽

try语句可以被嵌套,如果内层try中产生异常,会先匹配内层catch语句,不匹配再和外层catch语句进行匹配

对于一些资源来说,并不属于Java资源你,不由JVM进行管理,所以我们在打开后需要自己手动关闭,可以使用try开启资源自动管理功能,执行完语句, 资源自动关闭,交由JVM进行管理

// 语法
try(打开资源){

}
public void indexExp() {
    /*
     * Description: 对IndexOutOfBoundsException捕获,执行PlanB
     * @author: 苏无及
     * @date: 2022/8/6 19:56
     * @param:[]
     * @return:void
     */
    int[] array = {1, 2, 3, 4, 5};
    try {
        for (int i = 0; i < 6; i++) {
            System.out.println(array[i] + "");
        }
    } catch (IndexOutOfBoundsException e) {
        System.out.println("IndexOutOfBoundsException");
    }
}

/*
    测试
*/
@Test
public void test1(){
    CatchException exception = new CatchException();
    exception.indexExp();
}

2)throw

用于抛出异常,手动创建异常对象,不需要JVM创建对象

程序执行完throw之后立即停止执行,throw之后的语句不会执行,最邻近的try块检测自己是否有与异常对象相匹配的catchh语句,如果发现匹配的块,控制转向该语句,没有发现则使次包围的try进行检查,如果一直没有发现,程序将执行结束

所有的java内置的运行时异常创建对象,有两个构造函数,一个空参,一个带有一个字符串参数,参数用于指定异常的描述,可以通过print直接打印对象,或者使用getMessage()方法从而得到字符串

public void throwIndexExp() {
    /*
     * Description: throw抛出异常
     * @author: 苏无及
     * @date: 2022/8/7 20:43
     * @param:[]
     * @return:void
     */
    int[] array = {1, 2, 3, 4, 5};
    for (int i = 0; i < 6; i++) {
        if (i == 5){
            throw new IndexOutOfBoundsException("数组索引越界!");
        }
        System.out.println(array[i] + "");
    }
}

/*
    测试
*/
@Test
public void test2(){
    CatchException exception = new CatchException();
    try {
        exception.throwIndexExp();
    } catch (IndexOutOfBoundsException e) {
        System.out.println("数组索引越界");
    }
}

3)throws

用于在方法签名中,声明该方法可能抛出的异常类型,告知方法调用者

public void throwsIndexExp() throws IndexOutOfBoundsException{
    /*
     * Description: 使用throws声明异常类型
     * @author: 苏无及
     * @date: 2022/8/7 20:53
     * @param:[]
     * @return:void
     */
    int[] array = {1, 2, 3, 4, 5};
    for (int i = 0; i < 6; i++) {
        System.out.println(array[i] + "");
    }
}

/*
    测试
*/
@Test
public void test3(){
    CatchException exception = new CatchException();
    try {
        exception.throwsIndexExp();
    } catch (IndexOutOfBoundsException e) {
        System.out.println("数组索引越界!");
    }
}

4)finally

finally语句块总会被执行,不管catch中的语句是否执行。主要用于回收在try里打开的资源。

public void finallyExp(){
    /*
     * Description: 使用finally
     * @author: 苏无及
     * @date: 2022/8/7 20:59
     * @param:[]
     * @return:void
     */
    int[] array = {1, 2, 3, 4, 5};
    try {
        for (int i = 0; i < 6; i++) {
            System.out.println(array[i] + "");
        }
    } catch (IndexOutOfBoundsException e) {
        System.out.println("数组索引越界!");
    } finally {
        System.out.println("finally");
    }
}

/*
    测试
*/
@Test
public void test4(){
    CatchException exception = new CatchException();
    exception.finallyExp();
}

执行顺序

对于try、catch、finally的执行顺序:

  • 如果try中没有异常,try–>finally
  • 如果try中有异常,try–>catch–>finally
  • 当try、catch中有return时,也会执行finally,注意return的时候注意是否受finally的影响
  • finally中有return的时候,会直接在finally中退出,导致try、catch中的return失效

throw和throws的区别

  • trow出现在函数体中,throws出现在方法签名中
  • throws表示可能出现的异常类型,throw则一定抛出某个异常对象
  • 两者都是抛出异常,交由上次环境进行处理,如果还是不处理,JVM默认处理
  • throws可以表示抛出多个异常类型,用逗号分隔

自定义异常

  • 创建异常类(见名知意)
  • 继承内置异常类
  • 提供有参无参构造
// 自定义年龄越界异常类
public class AgeOutOfBoundsException extends RuntimeException {

    public AgeOutOfBoundsException() {
    }

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

Throwable的成员方法

  • String getMessage() 返回此throwable的详细消息字符串 返回的是在创建异常对象时,当作参数传入的字符串
throw new IndexOutOfBoundsException("数组索引越界!");
...

java.lang.IndexOutOfBoundsException: 数组索引越界!

  • String toString() 返回此可抛出的简短描述
java.lang.ArrayIndexOutOfBoundsException: 5
  • void printStackTrace 把异常的错误信息输出在控制台
java.lang.ArrayIndexOutOfBoundsException: 5
    at com.dong.exceptionDemo.CommonException.indexOutExp(CommonException.java:25)
    at com.dong.exceptionDemo.CommonExceptionTest.test1(CommonExceptionTest.java:20)

Original: https://www.cnblogs.com/suwuji/p/16559931.html
Author: 苏无及
Title: 异常详解

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/613091/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 18-网络七层架构

    七层架构主要包括 ①、 物理层 主要定义物理设备标准,如网线的接口类型、光纤的接口类型、各种传输介质的传输速率等。它的主要作用是传输比特流(就是由 1、0 转化为电流强弱来进行传输…

    数据库 2023年6月16日
    081
  • 分享一直在维护简单实用高效的C++Socket框架Swa-server(开源+源码)

    Swa-server 开源框架* 适用于中小型游戏,如:养成、RPG、棋牌等;应用软件,如:聊天室等* 已经封套好底层socket管理,sql请求处理、数据加密解密* 拿来即可开工…

    数据库 2023年6月14日
    094
  • MIT 6.824 Lab2C Raft之持久化

    书接上文Raft Part B | MIT 6.824 Lab2B Log Replication。 实验准备 实验代码: git://g.csail.mit.edu/6.824-…

    数据库 2023年6月14日
    067
  • 容器化 | 一文搞定镜像构建方式选型

    作者:安树博 青云科技 PaaS 中间件开发工程师从事 PaaS 中间件服务(Redis/Memcached 等)开发工作,热衷对 NoSQL 数据库领域内技术的学习与研究 官方镜…

    数据库 2023年5月24日
    081
  • ATM系统开发(Java版)

    ATM系统Java模拟开发总结 ATM系统开发 技术点分析 1.面向对象编程 每个用户的账户都是一个对象,所以需要设计账户类Accent用于创建账户对象封装账户信息。 2.使用集合…

    数据库 2023年6月16日
    073
  • 尤娜,我去面试了

    前情回顾 从前,有一个简单的通道系统叫尤娜…… 尤娜系统的第一次飞行中换引擎的架构垂直拆分改造 四种常用的微服务架构拆分方式 面试前几天 尤娜系统经过一次拆…

    数据库 2023年6月6日
    082
  • Linux定时任务调度

    任务调度是指系统在某个时间执行特定的命令或程序,任务调度主要有两种,第一种是系统工作,需要周而复始的执行,比如病毒扫描。第二种是个人用户工作,用户需要在某个特定的事件执行某些程序,…

    数据库 2023年6月16日
    094
  • Vue(十三)—过滤器filter,filters

    官网:https://cn.vuejs.org/v2/api/#filters https://cn.vuejs.org/v2/api/#Vue-filter 分为全局过滤器和局部…

    数据库 2023年6月16日
    093
  • 猿创征文|小而巧的API文档生成工具之smart-doc

    文章目录 smart-doc介绍 smart-doc特性 smart-doc的最佳搭档 谁在使用smart-doc smart-doc的优缺点 smart-doc和swagger区…

    数据库 2023年6月6日
    0269
  • [SQLServer]NetCore中将SQLServer数据库备份为Sql脚本

    描述: 最近写项目收到了一个需求, 就是将 SQL Server数据库备份为Sql脚本, 如果是My Sql之类的还好说, 但是在网上搜了一大堆, 全是教你怎么操作 SSMS的, …

    数据库 2023年6月9日
    0100
  • 设计模式之(4)——单例模式

    定义:单例模式属于创建型模式,该类负责创建自己的对象实例,并且确保只有单个对象被创建,同时该类提供了一种全局访问其唯一实例对象的方式;这个定义中有三个要点:1、单例类只能有一个实例…

    数据库 2023年6月14日
    086
  • dba+开源工具:MHA复刻版,轻松实现MySQL高可用故障转移(附下载)

    由于MHA(mha4mysql-manager)工具在2018年已经停止维护更新,且不支持GTID复制模式,在原版基础上增补功能难度较大,因此考虑将其重构。 参考了原版MHA的故障…

    数据库 2023年5月24日
    0109
  • 1. SQL

    404. 抱歉,您访问的资源不存在。 可能是URL不正确,或者对应的内容已经被删除,或者处于隐私状态。 [En] It may be that the URL is incorre…

    数据库 2023年5月24日
    093
  • SQL99相较于SQL92在多表查询时的新语法

    1.自然连接 NATURAL JOIN SQL99中新增的自然连接相当于SQL92中的等值连接。它可以自动的查询两个表中 所有的相同字段,然后进行等值连接。 在SQL92中: SE…

    数据库 2023年6月16日
    086
  • 【学习路线】– 凡人修仙,升级打怪路线图(留给2022的自己!发财加薪)

    B站真是程序员的福利站,不仅有鱼皮、狂神、水哥等等一系列的大佬,也有《凡人修仙传》这样的励志动漫,其实编程也是一样,我们也需要道友的支持、分享和协助,一路升级打怪。。。经验UpUp…

    数据库 2023年6月6日
    094
  • SqlSessionFactory工具类抽取

    多次SqlSessionFactory创建对象问题解决 SqlSessionFactory工具类抽取 问题描述: 当我们多次使用SqlSessionFactory创建并获取对象时会…

    数据库 2023年6月16日
    076
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球