异常详解

🦔异常

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

大家都在看

  • Nginx进阶篇—web模块及proxy代理

    server { #&#x5728;server{&#x4E0B;&#x9762;&#x8F93;&#x5165; sub_filter n…

    数据库 2023年6月14日
    097
  • Hello Word

    编写代码 public class  hello{ public static void main(String[] args){ System.out.print("H…

    数据库 2023年6月11日
    049
  • Javaer 面试必背系列!超高频八股之三色标记法

    可达性分析可以分成两个阶段 根节点枚举 从根节点开始遍历对象图 前文提到过,在可达性分析中,第一阶段 “根节点枚举” 是必须 STW 的,不然如果分析过程中…

    数据库 2023年6月6日
    098
  • 我是个怎样的人

    我是一个怎样的人 我是一个怎样的人, 我是一个虚伪的人. 我麻木的观察着这个世界, 对好坏, 真假, 我都去同样看待, 不去区分. 我是一个怎样的人, 我是一个善良的人. 我温柔的…

    数据库 2023年6月9日
    072
  • MySQL中常用的数据类型

    在写sql语句的时候,数据类型是避不可少的一个环节,以下是我在学习的过程中总结的数据类型,仅供参考: 数值类型 您可以在上表中看到,每种类型都有其对应的范围。如果它大于某个值,则不…

    数据库 2023年5月24日
    079
  • Mysql_事务_存储过程_触发器

    一、什么是事务? 事务(Transaction),一般是指要做的或所做的事情。在计算机术语中是指访问并可能更新数据库中各种数据项的一个程序执行单元(unit)。事务通常由高级数据库…

    数据库 2023年6月11日
    086
  • MySQL专题1: 字段和索引

    MySQL中存在 float, double 等非标准数据类型, 也有 decimal 这种标准数据类型 其区别在于: float, double等非标准类型在DB中保存的是近似值…

    数据库 2023年5月24日
    084
  • springboot~ApplicationContextAware与@Autowired注解

    ApplicationContextAware是一个接口,它提供一个方法setApplicationContext,当spring注册完成之后,会把ApplicationConte…

    数据库 2023年6月6日
    075
  • 设计模式遵循的设计原则

    一、什么是设计原则? 答:如果说设计模式是编写代码的一种套路,那么设计原则就是用来约束我们使用这种套路应该要遵循的规则,只有遵循了这些规则的设计模式编写出来的应用程序才具有更好的扩…

    数据库 2023年6月14日
    070
  • Windows 是最安全的操作系统

    建了一个用户交流群,我在群里说:”Windows 是最安全的操作系统。” 立刻引发了很多有意思的观点。我在群里一个人说不过大家,先篇文章把自己的论点罗列一下…

    数据库 2023年6月6日
    0238
  • VScode 添加jvm 启动参数 VScode 添加main方法参数

    问题场景. 本地环境使用的是 jdk 17 我需要在vscode 上运行一个jdk1.8 的项目 结果报错 : module java.base does not “o…

    数据库 2023年6月14日
    080
  • SQL语言的总结

    SQL语言分类:1.数据查询语言(DQL:Data Query Language),也称为”数据检索语句”,用以从表中查询获得数据,常用关键字SELECT …

    数据库 2023年5月24日
    065
  • Redis-缓存雪崩,击穿,穿透

    小结 布隆过滤器 工作原理:布隆过滤器是一个由初值为0的长度为L的bit数组和N个哈希函数组成。当有向数据库写入操作时,对键进行N次哈希值计算,并对计算后的值取L的模,对数组相应位…

    数据库 2023年6月11日
    054
  • MySQL启动报:[ERROR] The server quit without updating PID file

    修改配置后 MySQL启动不了,报错: 看见这个不要惊慌,先把刚才修改的配置注释掉,看是不是配置有误!大部分是手误造成。 如果不行,再尝试一下方法: 解决方法 : 给予权限,执行 …

    数据库 2023年6月14日
    077
  • 【黄啊码】这种PHP验证码你值得拥有(注:支持中文)

    csharp;gutter:true; width = $width; $this->height = $height; $this->codeNum = $codeN…

    数据库 2023年6月16日
    085
  • 有趣的特性:CHECK约束

    功能说明 在MySQL 8.0.16以前, CREATE TABLE允许从语法层面输入下列 CHECK约束,但实际没有效果: CHECK (expr) 在 MySQL 8.0.16…

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