1. 异常

1.1 什么是异常

什么是异常:不正常的情况。
在Java中,异常是扰乱程序正常流的事件。它是一个在运行时抛出的对象。

1.2 为什么要处理异常

为什么要进行异常处理:异常通常会破坏应用程序的正常流程,异常处理可以保持应用的正常流程,这是异常处理的核心优势。

2. 异常的继承层次

Screen Shot 2021-10-28 at 19.32.29.png

2.1 异常分类

在Java中,异常对象都是Throwable类的子类。
Throwable分为Error和Exception。

Error类层次结构描述了Java运行时系统的内部错误和资源耗尽错误。
应用程序不应该抛出这种类型的错误,当发生Error时,程序应该被中断。
常见的Error包括 OutOfMemoryError, VirtualMachineError, AssertionError。

Exception层次结构又分为两种:一是派生自RuntimeException;二是其他异常类。
两者的划分标准是:由编程错误导致的异常属于RuntimeExpection;如果程序本身没有问题,但由于像I/O错误这类问题导致的异常属于其他异常。
常见的运行时异常包括:ArithmeticException, NullPointerException, ArrayIndexOutOfBoundsException等。
其他异常包括:IOException, SQLException等。

Java语言将继承自Error类或RuntimeException类的所有异常都被称为非受检异常,所有其他的异常称为受检异常。
对于非受检异常,编译器在编译时不会被检查,但是会在运行时进行检查,程序应该尽量避免非受检异常。
对于受检异常,编译器在编译时会检查是否为所有受检异常提供了异常处理器。

2.2 checked Exception 受检异常

除了Error和RuntimeException之外的所有异常都被称为受检异常,比如等。
程序编译会检查checked exception。
checked exception需要在代码中明确检查和处理。

2.3 非受检异常

3. Java 异常关键字

try:指定要防止异常代码的block。try不能单独使用,必须和catch和finally一起使用。
catch:用于处理异常的代码块。必须放在try后面,catch后面可以跟着finally代码块。
finally:用于执行程序的必要代码块,通常用于释放资源。不管有没有发生异常finally代码块都会执行。
throw:用于抛出一个异常,通常用在catch代码块中。
throws:用于声明异常,方法签名的一部分,指定方法中可能会发生的异常。

4. 处理异常的一些指导原则

4.1 异常的选择

  1. 只在异常的情况下才使用异常。
  2. 对于可恢复的情况,抛出受检异常;对于程序错误,抛出运行时异常。不确定是否可恢复,抛出未受检异常。

如何决定使用受检异常or运行时异常?如果期望调用者能够适当地恢复,就应该使用受检异常。通过抛出受检异常,强迫调用者在一个catch子句中处理该异常,或者将该异常传播下去。
运行时异常表示编程错误,所以自定义的所有非受检异常都应该是RuntimeException的子类。

  1. 优先选择系统提供的异常 | 异常 | 使用场合 | | —- | —- | | IllegalArgumentException | 非null的参数值不正确 | | IllegalStateException | 不适合方法调用的对象状态 | | NullPointerException | 在禁止使用null的情况下参数值为null | | IndexOutOfBoundException | 下标参数值越界 | | ConcurrentModificationException | 在禁止并发修改的情况下,检测到对象的并发修改 | | UnsupportedOperationException | 对象不支持用户请求的方法 |

  2. 更高层的实现应该捕获低层的异常,同时抛出更高层的异常

4.2 异常的捕获

  1. 不要catch Throwable、Exception、Error、RuntimeException
  2. 不要忽略异常,即catch异常之后什么也不做,至少需要打印错误日志
  3. 只有当你想要处理一个异常的时候才去捕获它,否则,在方法签名处指明这个异常让调用者关注就好了。
  4. 不要同时打印并抛出异常。如果需要添加额外的信息,应该将异常捕获并包装在自定义的异常中,不要丢弃原有异常。
  5. 如果存在多个catch语句块中,优先捕获具体的异常。
  6. 不要捕获Java类库中定义的继承自RuntimeException的运行时异常

    4.3 异常的三种处理方式

    4.3.1 捕获后记录日志

    4.3.2 直接抛出

    4.3.3 包装后再抛出