参考资料:

JAVA异常详解

异常层次

image.png

一、异常介绍

什么是异常?

异常是指程序在运行过程中发生的,由于外部问题导致程序运行异常事件,异常的发生往往会中断程序的运行。在Java中,万物都是对象,异常本身也是一个对象,程序发生就会产生一个异常对象。

异常的分类

Throwable

  1. 是所有错误和异常的顶级父类,其他异常都派生于该类
  2. Throwable对象包含了其线程创建时线程执行的堆栈的快照,它还包含了给出错误更多的消息字符串
  3. 包含了cause(原因):另一个导致此throwable抛出的throwable。

Error

  1. Error是Throwable的子类,通常情况下应用程序不应该试图捕获的严重问题
  2. 是程序无法处理的错误。与代码编写者执行的操作无关

    Exception

    Exception以及它的子类,代表程序运行时发送的各种不期望发生的事件。可以被Java异常处理机制使用,是异常处理的核心。

非检查性异常

Error和RuntimeException以及他们的子类。
Java语言在编译时,不会提示和发现这样的异常,不要求在程序中处理这些异常。所以我们可以在程序中编写代码来处理这样的异常,也可以不做任何处理。对于这些错误或异常,我们应该修正代码,而不是通过异常处理。这样的异常发生的原因多半时由于我们的代码逻辑出现了问题。

  • ArithmeticException
  • ClassCastException
  • ArrayIndexOutOfBoundsException
  • NullPointerException

检查性异常

除了Error和RuntimeException的其他异常。
Java语言强制要求程序员为这样的异常做预备处理工作。在方法中要么使用try-catch语句捕获它并处理,要么throws子句声明抛出它,否则编译不会通过。

检查性异常就是在编译期间要求必须得到处理的异常,你必须在编译器处理了。

  • SQLException
  • IOException
  • ClassNotFoundException

二、异常处理机制

try-catch-finally

  1. 每一个catch块用于处理一个异常。异常匹配是按照catch块的顺序从上往下寻找的,只有第一个匹配的catch会得到执行。匹配时,不仅运行精确匹配,也支持父类匹配,因此,如果同一个try块下的多个catch异常类型有父子关系,应该将子类异常放在前面,父类异常放在后面,这样保证每个catch块都有存在的意义。
  2. Java中,异常处理的任务就是将执行控制流从异常发生的地方转移到能够处理这种异常的地方去。也就是说:当一个方法的某条语句发生异常时,这条语句的后面的语句不会再执行,它失去了焦点。执行流跳转到最近的匹配的异常处理catch代码块去执行,异常被处理完后,执行流会接着在“处理了这个异常的catch代码块”后面接着执行。

throws/thow 关键字

  1. 如果一个方法内部的代码会抛出检查性异常(checked exception),而方法自己又没有对这些异常完全处理掉,则java的编译器会要求你必须在方法的签名上使用 「throws」 关键字声明这些可能抛出的异常,否则编译不通过。
  2. throw 语句必须写在方法中,执行throw 语句的地方就是一个异常抛出点,它和由JRE自动形成的异常抛出点没有任何差别。