Day08:异常处理

异常处理

                      ┌───────────┐
                      │ Object   │
                      └───────────┘
                            ▲
                            │
                      ┌───────────┐
                      │ Throwable │
                      └───────────┘
                            ▲
                  ┌─────────┴─────────┐
                  │                   │
            ┌───────────┐       ┌───────────┐
            │   Error   │       │ Exception │
            └───────────┘       └───────────┘
                  ▲                   ▲
          ┌───────┘             ┌────┴──────────┐
          │                     │               │
 ┌─────────────────┐   ┌─────────────────┐┌───────────┐
 │OutOfMemoryError │... │RuntimeException ││IOException│...
 └─────────────────┘   └─────────────────┘└───────────┘
                                ▲
                    ┌───────────┴─────────────┐
                    │                         │
          ┌─────────────────────┐ ┌─────────────────────────┐
          │NullPointerException │ │IllegalArgumentException │...
          └─────────────────────┘ └─────────────────────────┘

Error:

  • OutOfMemoryError:内存耗尽

  • NoClassDefFoundError:无法加载某个Class

  • StackOverflowError:栈溢出

某些异常是应用程序逻辑处理的一部分,应该捕获并处理。例如:

  • NumberFormatException:数值类型的格式错误

  • FileNotFoundException:未找到文件

  • SocketException:读取网络失败

还有一些异常是程序逻辑编写不对造成的,应该修复程序本身。例如:

  • NullPointerException:对某个null的对象调用方法或字段

  • IndexOutOfBoundsException:数组索引越界

Exception又分为两大类:

  1. RuntimeException以及它的子类;

  2. RuntimeException(包括IOExceptionReflectiveOperationException等等)

Java规定:

  • 必须捕获的异常,包括Exception及其子类,但不包括RuntimeException及其子类,这种类型的异常称为Checked Exception。

  • 不需要捕获的异常,包括Error及其子类,RuntimeException及其子类。

捕获异常

捕获异常使用try...catch语句,把可能发生异常的代码放到try {...}中,然后使用catch捕获对应的Exception及其子类:

多catch语句:

  • 多个catch语句,每个catch分别捕获对应的Exception及其子类。多个catch只有一个能被执行。

  • 存在多个catch的时候,catch的顺序非常重要:子类必须写在前面。

finally语句

  • Java的try ... catch机制还提供了finally语句,finally语句块保证有无错误都会执行。

  • finally 语句不是必须的,并且总是最后执行。

如果没有发生异常,就正常执行try { ... }语句块,然后执行finally。如果发生了异常,就中断执行try { ... }语句块,然后跳转执行匹配的catch语句块,最后执行finally

某些情况下,可以没有catch,只使用try ... finally结构。

捕获多种异常

抛出异常

异常的传播

当某个方法抛出了异常时,如果当前方法没有捕获异常,异常就会被抛到上层调用方法,直到遇到某个try ... catch被捕获为止:

通过printStackTrace()可以打印出方法的调用栈,对于调试错误非常有用。

 

 public class Main {
    public static void main(String[] args) {
        try {
            process1();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
 static void process1() {
    process2();
 }
 
 static void process2() {
    Integer.parseInt(null); // 会抛出NumberFormatException
  }
 }
 //parseInt() 转换成整数

抛出异常

在catch中抛出新的异常时,要记得把原始异常的实例传进去。

捕获到异常并再次抛出时,一定要留住原始异常,否则很难定位第一案发现场!

在catch中抛出异常,不会影响finally的执行。JVM会先执行finally,然后抛出异常。

异常屏蔽

在极少数的情况下,我们需要获知所有的异常。如何保存所有的异常信息?方法是先用origin变量保存原始异常,然后调用Throwable.addSuppressed(),把原始异常添加进来,最后在finally抛出,当catchfinally都抛出了异常时,虽然catch的异常被屏蔽了,但是,finally抛出的异常仍然包含了它。

自定义异常

 

大型项目需要自定义异常。

自定义异常需要从RuntimeException继承,然后从BaseException派生自定义异常,自定义的BaseException应该提供多个构造方法。

 public class BaseException extends RuntimeException {
    public BaseException() {
        super();
    }
 
    public BaseException(String message, Throwable cause) {
        super(message, cause);
    }
 
    public BaseException(String message) {
        super(message);
    }
 
    public BaseException(Throwable cause) {
        super(cause);
    }
 }

NULLPointerException

空指针异常,俗称NPE。

如果一个对象为null,调用其方法或访问其字段就会产生NPE。

处理NULLPointerException

首先,必须明确,NullPointerException是一种代码逻辑错误,遇到NullPointerException,遵循原则是早暴露,早修复,严禁使用catch来隐藏这种编码错误。

尽量在定义成员变量时初始化。

 public class Person {
    private String name = "";
 }

定位NullPointerException

如果产生了NullPointerException,例如,调用a.b.c.x()时产生了NullPointerException,原因可能是a,b,c中的任一个为null.

在Java14中,JVM可以给出详细的信息告诉我们null对象到底是谁。

使用JDK Logging 日志

输出日志,而不是用System.out.println(),有以下几个好处:

  1. 可以设置输出样式,避免自己每次都写"ERROR: " + var

  2. 可以设置输出级别,禁止某些级别输出。例如,只输出错误日志;

  3. 可以被重定向到文件,这样可以在程序运行结束后查看日志;

  4. 可以按包名控制日志级别,只输出某些包打的日志;

  5. 可以……

总之就是好处很多啦。

 

 

 

posted @ 2021-10-14 18:31  027code  阅读(45)  评论(0)    收藏  举报