Java 异常

什么是异常

  1. 异常本质上是程序上的错误。
  2. 错误在我们编写程序的过程中会经常发生,包括编译期间和运行期间的错误。
  3. 在程序运行过程中,意外发生的情况,背离我们程序本身的意图的表现,都可以理解为异常。

Throwable(异常的根类)

  1. Error(Java 虚拟机出现问题)
    • Error 是程序无法处理的错误,表示运行应用程序中比较严重的问题。
    • 它们在应用程序的控制和处理能力之外,而且绝大多数是程序运行时不允许出现的状况。
    • 对于设计的合理的应用程序来说,即使确实发生了错误,本质上也不应该试图去处理它所引起的异常状况。
    • 常见错误
      • 虚拟机错误 VirtualMachineError
      • 内存溢出 OutOfMemoryError
      • 线程死锁 ThreadDeath
  2. Exception
    • Exception 是程序本身可以处理的异常。异常处理通常指针对这种类型异常的处理。
    • 检查异常 Checked Exception
      • 编译器要求必须处置的异常。(编码阶段)
      • 除了 RuntimeException 及相关子类,其它异常都属于 Checked Exception
        • IO 异常 IOException
        • SQL 异常 SQLException
        • 等等
    • 非检查异常 Unchecked Exception
      • 编译器不要求强制处置的异常(运行阶段)
      • 包含 RuntimeException 及相关子类
        • 空指针异常 NullPointerException
        • 数组下标越界异常 ArrayIndexOutOfBoundsException
        • 算数异常 ArithmeticException
        • 类型转换异常 ClassCastException
        • 等等…
    • System.exit(1); 终止程序运行

throw & throws

  1. throws
    • 可以通过 throws 声明将要抛出何种类型的异常,通过 throw 将产生的异常抛出。
    • 如果一个方法可能出现异常,但没有能力处理这种异常,可以在方法声明处用 throws 子句来声明抛出异常。
    • throws 语句用在方法定义时声明该方法要抛出的异常类型。
    • 当方法抛出异常列表中的异常时,方法将不对这些类型及其子类类型的异常做处理,而抛向调用该方法的方法,由他去处理。
  2. throw
    • throw 用来抛出一个异常。
      • 例如:throw new IOException():
    • thorw 抛出的只能够是可抛出类 Throwable 或者其子类的实例对象。
      • 例如:throw new String(“出错了”); 是错误的
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        public void method(){
        try{
        // 代码段1
        throw new 异常类型();
        }catch(异常类型 ex){
        // 对异常处理的代码段2
        }
        }
        public void method() throws 异常类型{
        // 代码段1
        throw new 异常类型();
        }
    • 作用
      • 规避可能出现的风险
      • 完成一些程序的逻辑
    • throw 抛出异常对象的处理方案
      • 通过 try…catch 包含 throw 语句 —— 自己抛出自己处理
      • 通过 throws 在方法声明抛出异常类型 —— 谁调用谁处理 —— 调用者可以自己处理,也可以继续上抛。此时可以抛出与 throw 对象相同类型或者其父类
      • 当子类重写父类抛出异常方法时,声明的异常必须是父类方法所声明异常的同类或子类。

自定义异常

  1. 基本概念
    • 使用 Java 内置的异常类可以描述在编程时出现的大部分异常情况。
    • 也可以通过自定义异常描述特定业务产生的异常类型。
    • 所谓自定义异常,就是定义一个类,去继承 Throwable 类或者它的子类
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      public class TestException extends Exception{
      public TestException(){
      super("向父类抛的异常消息");
      }
      }

      public static void test() throw TestException{
      <代码块>
      throw new TestException();
      }

异常链

  1. 基本概念
    • 有时候我们会捕获一个异常后在抛出另一个异常
    • 顾名思义就是:将异常发生的原因一个传一个串起来,即把底层的异常信息传个上层,这样逐层抛出。
  2. Exception e1 = new Exception(“异常消息”); e1.initCause(e);

如何处理异常

  1. 在 Java 应用程序中,异常处理机制为
    • 抛出异常(先抛出,才能被捕获)
    • 捕获异常
  2. 对于运行时异常,错误或可检查异常,Java 技术所要求的异常处理方式有所不同。
    • 1、对于可查异常必须捕捉、或者声明抛出
    • 2、允许忽略不可查的 RuntimeException(含子类)和 Error(含子类)
  3. 通过 5 个关键字来实现
    • 捕获异常
      • try(执行可能产生异常的代码)
      • catch(捕获异常)
      • finally(无论是否发生异常 代码总能执行)
    • 声明异常
      • throws(声明可能要抛出的异常)
    • 抛出异常
      • throw (手动抛出异常)
  4. 规则说明
    • try-catch-finally
      • try 块后可接零个或多个catch块,如果没有 catch 块,则必须跟一个finally块。
  5. 自定义异常
  6. 异常链

实际应用总结

  1. 处理运行异常时,采用逻辑去合理规避同时辅助 try-catch 处理
  2. 在多重 catch 块后面,可以加一个 catch(Exception) 来处理可能被遗漏的异常
  3. 对于不确定的代码,也可以加上 try-catch,处理潜在的异常
  4. 尽量去处理异常,切忌知识简单的调用 printStackTrace() 去打印输出
  5. 具体如何处理异常,要根据不同的业务需求和异常类型去决定
  6. 尽量添加 finally 语句块去释放占用的资源(关闭文件、关闭 sql 链接)等