• Java异常


    Java笔记


    一、简介

    1. 一个健壮的程序必须能够处理各种异常。

    2. 我们应该如何处理异常?两种方式:

      • 返回约定错误码,例如200表示成功。
      • 在语言层面提供异常处理机制。
    3. 必要性说明

      • 异常需要被分门别类区处理的,不推荐直接使用 Exception 类捕获所有异常,这不是一个好的习惯。
      • 发生异常时,程序会被从异常发生处开始中断。
      • 异常与错误,并不一样。Throwable 中有两个体系:Error和Exception,虽然两者都会被抛出,但是 Error 表示严重的错误,程序一般对此无能为力。
      • 在Java体系中存在一些必须要捕获的异常。如果这些异常没有对应的捕获语句,那么编译器会编译失败。
      • 如果在方法头中标记了可能抛出的异常,那么我们在编写try()语句的时候就可以不用编写catch语句。【注意是 try() 而不是 try 】
      • 所有未捕获的异常,最终都会在main()中出现,我们必须要在main方法中设法捕获所有异常

      image-20220817184832653

    4. Java异常库

      Java异常库

    5. 异常处理顺序原则:从小到大,最后 Exception 包揽全部。

      try {
          //
      } catch (IOException e) {
          // io error:
      } catch (Exception e) {
          // other error:
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
    6. 概念:异常栈

      • 当发生异常时,会按照顺序依次抛出异常,所以Java程序中存在异常栈。
      • printStackTrace()方法负责打印异常栈,每层调用都会给出对应的源代码行号,这对于调试错误非常有用。
      java.lang.NumberFormatException: null
          at java.base/java.lang.Integer.parseInt(Integer.java:614)
          at java.base/java.lang.Integer.parseInt(Integer.java:770)
          at Main.process2(Main.java:16)
          at Main.process1(Main.java:12)
          at Main.main(Main.java:5)
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6

      上述信息表示:numberFormatException是在Java.lang.integer.parseInt方法中抛出的,从下往上看,调用层依次是

      image-20220722115711984

    7. 关键性的Cause by

      • Cause by 通常是具体的抛出异常原因,可口语化表示。
      • 自定义 Cause by:initCause 初始化异常对象。
      try {
          int a = 1 / 0;
      } catch (Exception ex) {
        
          throw new Exception().initCause(new Throwable("自定义"));
        
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
    8. 4种异常类【输出方法】

      • 原生
      int a = 1 / 0;
      
      • 1
      Exception in thread "main" java.lang.ArithmeticException: / by zero
      	at com.thinkstu.csdn.controller.test.main(test.java:9)
      
      • 1
      • 2
      • printStackTrace():同原生
      try {
          int a = 1 / 0;
      } catch (Exception ex) {ex.printStackTrace();}
      
      • 1
      • 2
      • 3
      Exception in thread "main" java.lang.ArithmeticException: / by zero
      	at com.thinkstu.csdn.controller.test.main(test.java:9)
      
      • 1
      • 2
      • getMessage():简短
      try {
          int a = 1 / 0;
      } catch (Exception ex) {
          System.out.println(ex.getMessage());
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      / by zero
      
      • 1
      • toString():折中
      try {
          int a = 1 / 0;
      } catch (Exception ex) {
          System.out.println(ex.toString());
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      java.lang.ArithmeticException: / by zero
      
      • 1
    9. 关于finally语句的几个特点:

      • finally语句不是必须的。
      • finally语句总是最后执行。
      • 就算不发生异常,finally语句也会被执行。
    10. 异常参数混合使用规则:|号分割。

      public static void main(String[] args) {
          try {
              process1();
      
          } catch (IOException | NumberFormatException e) {
          } 
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
    11. 概念:异常转换、异常屏蔽

      • 如果在 catch 里把异常捕获,又把异常抛出去(可以这样做),那么最终异常还是会被抛出该方法,俗称**【异常转换】**。

      • 注意,在异常转换时需要把原始的异常信息补充进去,以免丢失原始的异常信息、难以定位第一案发现场。另外,再次抛出异常并不会影响原 finally 语句的执行,此时程序的执行顺序为 try → catch → finally → throw 。

      • 但是,如果是在 finally 语句中抛出了异常,那么结果就是 finally 中的异常会被正确抛出,而 catch 里的异常则不会被抛出,这种情况需要格外注意,俗称**【异常屏蔽】**。

      try {
          process();
      } catch (NullPointerException oldMsg) {
        
          // 保留原始的异常信息
          throw new IllegalArgumentException( oldMsg );
        
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      try {
           process();
      } catch (Exception e) {
          throw new RuntimeException(e);
      } finally {
        
          // 屏蔽了 catch 中新抛出的异常
          throw new IllegalArgumentException();
        
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10

    二、空指针异常

    空指针异常是 Java 异常体系中重要章节

    1. 空指针异常(NPE):Null Point Exception。

    2. 产生原因:如果一个对象为 null ,那么调用该对象方法或字段就会产生空指针异常 NullPointException ,这个异常通常是由JVM抛出的。

    3. 必要性说明

      • 空指针是一种代码逻辑错误。
      • 指针概念源于C语言,Java 中并无指针。我们所说的 Java 空指针异常实际上指的是 Java 引用异常(Null Reference),不过两者的差别不大。
      • 好的编程习惯可以在一定程度上避免空指针的发生。例如在定义 String 变量时,使用空字符串""而不是默认的 null 可以避免 NullPointException 的发生。
      // 好的编程习惯范例
      public String[] test1(String file) {
        private String name = "";
      	if (getFileSize(file) == 0) {
            return new String[0];
        }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7

    三、自定义异常

    尽量使用 JDK 提供的异常类型(存在即使用),而不是自定义异常。

    1. 简介
      • 大型项目需要自定义异常,小项目则不然。
      • 自定义异常需要保持合理的【异常继承体系】。
    2. 简单实现
    • 自定义BaseException作为自定义的“根异常”。

    • BaseException 继承自 RuntimeException 且提供多个构造方法。

    • 由 BaseException 派生其他异常。

      // 必须将调用父类 super 方法,保护异常案发现场
      public class BaseException extends RuntimeException {
          
          public BaseException() {
              super();
          }
      
          public BaseException(String msg, Throwable cause) {
              super(msg, cause);
          }
      
          public BaseException(String msg) {
              super(msg);
          }
      
          public BaseException(Throwable cause) {
              super(cause);
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
  • 相关阅读:
    基于MATLAB的电流、电压互感器特性的仿真分析
    罗汉果位,八风拂面
    035:vue项目中 radio和checkbox美化方法
    DAY46 139.单词拆分 + 多重背包 + 背包问题总结篇
    【高等数学】矩阵与向量组的秩和等价
    【国漫逆袭】人气榜,小医仙首次上榜,霍雨浩排名飙升,不良人热度下降
    你知道Golang的模板怎么用吗?带你了解动态文本的生成!
    干货|app自动化测试之模拟器控制
    windows mysql安装卸载,多版本mysql方案
    多探头高频读写器|读卡器CK-FR104ANS系列安装与新旧功能对比分析
  • 原文地址:https://blog.csdn.net/qq_35760825/article/details/126394036