• 【关于Java:认识异常】



    一、1. 异常概念与体系结构

    1.1 异常的概念

    在写代码的过程中总会出现的一些问题bug,有时很难通过代码去解决它
    在Java中,将在程序执行过程中发生的不正常行为称为异常。

    异常也分类:

    1.2 常见的异常

    1.算数异常

    public class Test {
        public static void main(String[] args) {
            System.out.println(10/0);
    
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在这里插入图片描述

    2.数组越界异常

    public class Test {
        public static void main(String[] args) {
            int[] arr = {1, 2, 3};
            System.out.println(arr[100]);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在这里插入图片描述

    3.空指针异常

    public class Test {
        public static void main(String[] args) {
            int[] arr = null;
            System.out.println(arr[0]);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在这里插入图片描述

    1.3 异常的体系结构

    异常种类繁多,为了对不同异常或者错误进行很好的分类管理,Java内部维护了一个异常的体系结构
    在这里插入图片描述
    从上图中可以看到:

    1. Throwable:是异常体系的顶层类,其派生出两个重要的子类, ErrorException
    2. Error(错误):指的是Java虚拟机无法解决的严重问题,比如:JVM的内部错误资源耗尽等,典型代表:StackOverflowError和OutOfMemoryError,一旦发生回力乏术。
    public class Test {
        public static void func(){
            func();
        }
    
        public static void main(String[] args) {
            func();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    在这里插入图片描述

    1. Exception(异常):异常产生后程序员可以通过代码进行处理,使程序继续执行。平时所说的异常就是Exception。

    1.4 异常的分类

    异常可能在编译时发生,也可能在程序运行时发生,根据发生的时机不同,可以将异常分为:

    1. 编译时异常

    在程序编译期间发生的异常,称为编译时异常,也称为受检查异常
    还没来得及运行,在写代码的时候就报异常了。
    在这里插入图片描述

    2. 运行时异常(RuntimeException)

    在程序执行期间发生的异常,称为运行时异常,也称为非受检查异常

    RunTimeException以及其子类对应的异常,都称为运行时异常。RuntimeException有很多很多子类比如:NullPointerException、ArrayIndexOutOfBoundsException、ArithmeticException。

    二、 异常的处理方式

    2.1 防御式编程

    1. LBYL:
      Look Before You Leap. 在操作之前就做充分的检查,即:事前防御型
      每做一步都要进行一次检查,
      缺陷:正常流程和错误处理流程代码混在一起, 代码整体显的比较混乱。
    boolean ret = false;
    ret = 登陆游戏();
    if (!ret) {
    处理登陆游戏错误;
    return;
    }
    ret = 开始匹配();
    if (!ret) {
    处理匹配错误;
    return;
    }
    ret = 游戏确认();
    if (!ret) {
    处理游戏确认错误;
    return;
    }
    ret = 选择英雄();
    if (!ret) {
    处理选择英雄错误;
    return;
    }
    ret = 载入游戏画面();
    if (!ret) {
    处理载入游戏错误;
    return;
    }
    ......
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    2.2 EAFP:(异常处理的核心思想)

    It’s Easier to Ask Forgiveness than Permission. "事后获取原谅比事前获取许可更容易"也就是先操作, 遇到问题再处理,即:事后认错型
    优势:正常流程和错误流程是分离开的, 程序员更关注正常流程,代码更清晰,容易理解代码

    try {
    登陆游戏();
    开始匹配();
    游戏确认();
    选择英雄();
    载入游戏画面();
    ...
    } catch (登陆游戏异常) {
    处理登陆游戏异常;
    } catch (开始匹配异常) {
    处理开始匹配异常;
    } catch (游戏确认异常) {
    处理游戏确认异常;
    } catch (选择英雄异常) {
    处理选择英雄异常;
    } catch (载入游戏画面异常) {
    处理载入游戏画面异常;
    }
    ...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    三、 异常的处理流程

    在Java中,异常处理主要的5个关键字:throw、try、catch、final、throws

    处理异常的前提是得抛出异常

    3.1 异常的抛出

    在编写程序时,如果程序中出现错误,此时就需要将错误的信息告知给调用者。
    如果出现bug,又不想解决的时候,可以借助throw关键字,抛出一个指定的异常对象,当调用者调用时,调用者就知道这里有一个异常了。

    抛出异常的方式有很多种
    1.某段程序抛出
    2.throw关键字抛出,一般用于抛出自定义的异常

    throw关键字

    public class Test {
        public static void main(String[] args) {
            int a=10;
           if(a==10){
               throw new NullPointerException("hahaha!");
           }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    【注意事项】

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

    throws关键字

    使用在方法的声明之后
    作用:告诉方法的调用者,调用这个方法,会抛出一个XXX异常。
    应用场景:处在方法声明时参数列表之后,当方法中抛出编译时异常,用户不想处理该异常,此时就可以借助throws将异常抛给方法的调用者来处理。即当前方法不处理异常,提醒方法的调用者处理异常。
    在这里插入图片描述

    在这里插入图片描述

    【注意事项】

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

    try catch

    在这里插入图片描述
    编译时异常(受查异常),必须要处理
    所以:
    在这里插入图片描述
    但是,这个异常最终没有被程序员处理,实际上是交给JVM处理 。

    如果不想要JVM处理,想要自己处理,那么就用到try catch

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    使用try catch可以自己抛出异常的代码,让程序正常进行

    下面的代码在第二次打印的时候异常了,导致最后一个代码没有打印出来,
    因为这种情况就是交给JVM处理,当JVM处理时,就会异常终止。

    所以就出现了try catch来弥补这个缺点,使程序正常运转。
    在这里插入图片描述

    try catch使用方法:
    把可能异常的代码用try 包裹起来,在catch括号里面抛出可能异常的类型,只有当catch捕捉到了这个异常,才会执行catch里面的内容,才能使后面的代码正常运行。
    所以有一点注意的是:一定要写对异常的类型

    public class Test {
        public static void main(String[] args) {
            System.out.println("before...");
        try {
        System.out.println(10/0);
    
        }catch (ArithmeticException e){
        System.out.println("我来处理异常ArithmeticException异常了");
        }
        System.out.println("after...");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    在这里插入图片描述

    在这里插入图片描述
    如果不知道是什么异常,或者异常有很多个,就写多几个catch

    public static void main(String[] args) {
            System.out.println("before...");
        try {
        System.out.println(10/0);
        }catch (ArithmeticException e){
        System.out.println("我来处理异常ArithmeticException异常了");
        }catch(NullPointerException a){
            System.out.println("我来处理异常NullPointerException异常了");
            }
    
        System.out.println("after...");
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    如果想知道是哪一行代码有异常,可以这样写

       public static void main(String[] args) {
            System.out.println("before...");
        try {
        System.out.println(10/0);
        }catch (ArithmeticException e){
            e.printStackTrace();
        System.out.println("我来处理异常ArithmeticException异常了");
        }catch(NullPointerException a){
            System.out.println("我来处理异常NullPointerException异常了");
            }
    
        System.out.println("after...");
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

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

    【注意事项】

    1. try块内抛出异常位置之后的代码将不会被执行
    2. 如果抛出异常类型与catch时异常类型不匹配,即异常不会被成功捕获,也就不会被处理,继续往外抛,直到 JVM收到后中断程序----异常是按照类型来捕获的
      3.不能直接用父类接受所有的异常子类,因为此时异常不精准。

    如果异常之间具有父子关系,一定是子类异常在前catch,父类异常在后catch,否则语法错误:

    在这里插入图片描述

    子类在前,父类在后是可以的,父类充当了一个垫后的作用。
    在这里插入图片描述

    总结

    例如:以上就是今天要讲的异常的内容,内容多但比较容易理解,多看看复盘一下就能掌握啦。

  • 相关阅读:
    【今日文章】:Web端常用的Observer监听器
    龙蜥开发者说:开源是场马拉松!来自广州大学姚同学的开源成长记 | 第 13 期
    记忆化搜索
    java中的this引用和对象的构造及初始化
    温泉镇旅游微信小程序的设计与实现(论文+源码)_kaic
    [Java]前中后序遍历二叉树/递归与非递归
    使用 Python 和 Selenium 进行网络抓取
    <C++>多态的实战,详解三个具体案例
    概括23种设计模式
    (38)STM32——NRF24L01无线通信
  • 原文地址:https://blog.csdn.net/2301_76496134/article/details/132758079