• 【JavaSE】认识异常(上篇)


    ✨hello,进来的小伙伴们,大家好呐!✨

    🎁🎁系列专栏:【JavaSE】

    🍱🍱本篇内容:异常的认识,异常分为几类,如何处理异常等等。

    🍮🍮作者简介:一名大二即将升大三的科班编程小白,我很平凡,学会努力!

    🥞🥞这里给大家推荐一个很好的刷题平台——牛客网!

    点击链接注册,开始刷题之路!

    c8c91132565a40b6a8d5309bc40e70d9.png

     一、定义

    在Java中,将程序执行过程中发生的不正常行为称为异常

    实例:1算术异常

    1. public class TestDemoX {
    2. public static void main(String[] args) {
    3. int a = 10;
    4. System.out.println(a/0);
    5. }
    6. }

    82aecfe2a7474559bc298a0fe2b14ca9.png

    实例2:数组越界异常

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

    500d5784c50048c89b0b35aa1ea7cfea.png

     实例3:空指针异常

    1. public class TestDemoX {
    2. public static void main(String[] args) {
    3. int[] arr1 =null;
    4. System.out.println(arr1.length);
    5. }
    6. }

    d417f66aaa684c9b91e6602238ec4e33.png

    注意这些异常都继承于Exception。

     二、 异常的分类

    1、编译时异常

    1. public class Person {
    2. private String name;
    3.   private String gender;
    4.   int age;
    5.   // 想要让该类支持深拷贝,覆写Object类的clone方法即可
    6.   @Override
    7.   public Person clone() {
    8.     return (Person)super.clone();
    9.  }
    10. }

    2、运行时异常

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

    这里我们借助JavaAPI,可以知道RunTimeException以及其子类对应的异常,都称为运行时异常。

    f74aba2882954cb58f912c241f62fa4b.png

     注意:编译时出现的语法性错误,不能称之为异常!

    比如我们这里把println写成了prinln 这就称为语法错误,而不是异常了!

            System.out.prinln();

    三、异常的处理

    1.了解异常

    我们刚才提到,当程序出现异常的时候,我们没去处理,那么这个时候程序就终止了,不会再继续下去!

    1. public class TestDemoX {
    2. public static void main(String[] args) {
    3. int a = 10;
    4. System.out.println(a/0);
    5. System.out.println("执行后续代码!");
    6. }
    7. }

    可以发现,后续代码没有被执行! 这个时候异常会交给jvm来处理,程序会立即终止!

    73e4540f151646c0bc803e4f4cfb3349.png

     2、异常处理

    这里我们以一个游戏登录来描述:

    try里面存放可能出现异常的代码;

    catch里面捕获可能出现的异常;

    注意:一个try可以对应多个catch。

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

    我们还是以刚才的算术异常来举例:

    1. public class TestDemoX {
    2. public static void main(String[] args) {
    3. int a = 10;
    4. try{
    5. System.out.println(a/0);
    6. }
    7. catch (ArithmeticException e){
    8. System.out.println("出现了算术异常!");
    9. }
    10. System.out.println("执行后续代码!");
    11. }
    12. }

    运行结果:我们发现catch捕获异常之后,后续代码照样执行!

    126395b743584cd59b5f811401ac4c05.png

     那么我们如何得知出现了何种异常呢?很简单,我们只需要通过(参数)e.printStackTrace();便可以快速的定位异常的位置。

    f9858cbb0c2c4ac8bbe66dbbf858098a.png

    运行结果: 450973de4a124af58f2e9ef41a4c3067.png

    注意,这里没有同时抛出两个以上的异常的说法,就是catch捕获到异常以后,会执行catch{}里面的内容,写个例子给大家看一下:

    1. public class TestDemoX {
    2. public static void main(String[] args) {
    3. int a = 10;
    4. try{
    5. System.out.println(a/0);
    6. int[] arr = {1,2,3,4};
    7. arr = null;
    8. System.out.println(arr[100]);
    9. }
    10. catch (ArithmeticException e){
    11. e.printStackTrace();
    12. System.out.println("出现了算术异常!");
    13. }
    14. catch(ArrayIndexOutOfBoundsException e){
    15. e.printStackTrace();
    16. System.out.println("数组越界异常!");
    17. }
    18. catch (NullPointerException e){
    19. e.printStackTrace();
    20. System.out.println("空指针异常!");
    21. }
    22. System.out.println("执行后续代码!");
    23. }
    24. }

    运行结果:我们发现,捕获到算术异常以后,剩下的代码并没有被执行,这正好验证了没有同时抛出多个异常的说法!

    efad44dda1ef47df9cf23c0cfd7c0413.png

     注意:如果异常之间存在父子类关系,那么把父类放在最后!

    822a8dbd5e074d6bb07d5b0864d1a3f2.png

     3.异常的抛出

    在Java中,可以借助throw关键字,抛出一个指定的异常对象,将错误信息告知给调用者。

    语法:throw new XXXException("异常产生的原因");

    实例:实现一个获取数组中任意位置元素的方法。

    1. public static int getElement(int[] array, int index){
    2.   if(null == array){
    3.     throw new NullPointerException("传递的数组为null");
    4. }
    5.    
    6.   if(index < 0 || index >= array.length){
    7.     throw new ArrayIndexOutOfBoundsException("传递的数组下标越界");
    8.  }
    9.  
    10.   return array[index];
    11. }
    12. public static void main(String[] args) {
    13.   int[] array = {1,2,3};
    14.   getElement(array, 3);
    15. }

    运行结果:

    bc717346688d40e88c25d04e0cb11cad.png

     注意:

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

    4、异常的捕获

    1 异常声明throws
    处在方法声明时参数列表之后,当方法中抛出编译时异常,用户不想处理该异常,此时就可以借助throws将异常抛给方法的调用者来处理。即当前方法不处理异常,提醒方法的调用者处理异常

    实例:

    1. public class Config {
    2.   File file;
    3.   // public void OpenConfig(String filename) throws IOException,FileNotFoundException{
    4.   // FileNotFoundException 继承自 IOException
    5.   public void OpenConfig(String filename) throws IOException{
    6.     if(filename.endsWith(".ini")){
    7.       throw new IOException("文件不是.ini文件");
    8.    }
    9.    
    10.     if(filename.equals("config.ini")){
    11.       throw new FileNotFoundException("配置文件名字不对");
    12.    }
    13.     // 打开文件
    14.  }
    15.   public void readConfig(){
    16.  }
    17. }

    结论:

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

    4. 调用声明抛出异常的方法时,调用者必须对该异常进行处理,或者继续使用throws抛出。

    5d86a58389df47da96183acb95e13d28.jpeg

    5、finally

    在写程序时,有些特定的代码,不论程序是否发生异常,都需要执行,比如程序中打开的资源:网络连接、数据库连接、IO流等,在程序正常或者异常退出时,必须要对资源进进行回收。

    实例:简单输入的数据流关闭。

    1. public class Testdemo3 {
    2. public static void main(String[] args) {
    3. Scanner sc = new Scanner(System.in);
    4. try{
    5. int n = sc.nextInt();
    6. }catch (InputMismatchException e){
    7. e.printStackTrace();
    8. System.out.println("输入数据不匹配!");
    9. }
    10. finally {
    11. System.out.println("执行了finally部分,一般用来关闭资源!");
    12. sc.close();
    13. }
    14. }
    15. }

    运行结果:我们故意输入字符串,我们发现finally部分的代码依然会被执行!

    42cecd38018b445f8502dea896bfe3e1.png【异常处理流程总结】
    🥧程序先执行 try 中的代码。
    🍩如果 try 中的代码出现异常, 就会结束 try 中的代码, 看和 catch 中的异常类型是否匹配。
    🍿如果找到匹配的异常类型, 就会执行 catch 中的代码。
    🍬如果没有找到匹配的异常类型, 就会将异常向上传递到上层调用者。
    🍭无论是否找到匹配的异常类型, finally 中的代码都会被执行到(在该方法结束之前执行)。
    🥯如果上层调用者也没有处理的了异常, 就继续向上传递。
    🥝一直到 main 方法也没有合适的代码处理异常, 就会交给 JVM 来进行处理, 此时程序就会异常终止。

  • 相关阅读:
    Sharding-Jdbc分库分表集成Mybatis-Plus+多数据源管理
    LCR 078. 合并 K 个升序链表
    .NET开源、功能强大、跨平台的图表库 - LiveCharts2
    java版直播商城免费搭建平台规划及常见的营销模式+电商源码+小程序+三级分销+二次开发
    【LeetCode与《代码随想录》】贪心算法篇:做题笔记与总结-JavaScript版
    【热门前端【vue框架】】——vue框架和node.js的下载和安装保姆式教程
    高斯分布与高斯过程
    goquery库编写程序
    Rockland一抗丨视紫红质抗体解决方案
    电脑上给照片调色LrC2022中文
  • 原文地址:https://blog.csdn.net/m0_62426532/article/details/126612941