目录

Life in Flow

知不知,尚矣;不知知,病矣。
不知不知,殆矣。

X

异常

错误

 程序运行时发生的不被期望的事件,阻 ⽌了程序按照预期正常执行。常见程序错误分三类:

  • 编译错误:没有遵循语法规范。
  • 运行时错误:程序在执行时发生的错误。
  • 逻辑错误:程序没有按照预期的逻辑顺序执行。

Java 异常体系

 个 java.lang.Throwable 类是 Java 中所有错误和异常的超类,其派生的两个子类分别为:Error、Exception。

Java 异常体系

Error
 包含大量子类,用于抽象出错后程序无法处理的情况,例如:OutOfMemoryError。

Exception
 包含大量子类,用于抽象程序本身可以处理的异常。例如:ArrayIndexOutOfBoundException。同时 Exception 又派生出量大子类:

  • 运行时异常(不可查异常):RuntimeException 类及其子类,例如:ArrayIndexOutOfBoundsException。ClassNotFoundException。
  • 非运行时异常(编译时可查异常):所有 Exception 类及其子类(RuntimeException 类及其子类除外),例如:IOException。

Java 内置异常体系分类

非运行时异常(编译时可查异常)
 必须要在方法里捕获或者抛出。

  • ClassNoFoundException 应 ⽤程序试图加载类,找不到对应的类
  • IllegalAccessException 拒绝访问 ⼀个类的时候
  • NoSuchFieldExcetion 请求的变量不存在
  • NoSuchMethodException ⽅法不存在
  • ……

运行时异常(不可查异常)

  • ArrayIndexOutOfBoundsException 数组索引越界
  • ClassCastException 强制失败抛出异常
  • NullPointerException 需要对象的地 ⽅使 ⽤ null 时,抛出该异常
  • NumberFormatException 将字符串转换成 ⼀种数值类型,但该字符串不能转换为适当 格式时,抛出该异常
  • ……

Throwable 类核心方法

  • public String getMessage():异常的详细信息。
  • public Throwable getCause():异常原因。
  • public void printStackTrace():打印错误的堆栈信息,即错误输出流,可以看到错误原因和所在位置。
  • public StackTraceElement [] getStackTrace():堆栈层次的数组,下标为 0 的元素代表栈顶,最后 ⼀个元素代表 ⽅法调 ⽤堆栈的栈底。
 1package com.javase.demo;
 2
 3import org.junit.jupiter.api.Test;
 4import org.junit.runner.RunWith;
 5import org.springframework.boot.test.context.SpringBootTest;
 6import org.springframework.test.context.junit4.SpringRunner;
 7
 8@RunWith(SpringRunner.class)
 9@SpringBootTest(classes = DemoApplication.class)
10class DemoApplicationTests {
11
12    @Test
13    public void tryCatchTesting() {
14        try {
15            int result = 2/0;
16            System.out.println(result);
17        } catch (Exception e) {
18            e.printStackTrace();//打印错误的堆栈信息。可以看到错误原因和所在位置。
19            String msg = e.getMessage();
20            StackTraceElement[] arr = e.getStackTrace();
21        }
22    }
23}
24
25//java.lang.ArithmeticException: / by zero
26//at com.javase.demo.DemoApplicationTests.tryCatchTesting(DemoApplicationTests.java:15

Try Catch 进行异常捕获

  • try 后 ⾯跟 ⼀个或多个 catch 块,或 ⼀个 finally 块,或两者的组合
  • catch 不能独立于 try 而单独存在
  • 如果代码没有匹配到对应的异常类进 ⾏捕获,则默认打印异常堆栈
  • 代码中发 ⽣异常,异常被抛给第 ⼀个 catch 块, 如果不匹配则继续往下 ⼀个 catch 进 ⾏传递
  • finally 代码块中的代码总会被执 ⾏
  • try,catch 和 finally 块有两种可能的组合:try-catch-finally 或 try-finally
 1try {
 2            //发生异常的代码(此处中断,产生异常,进入catch代码块)1
 3	    //其他代码(不会执行)	
 4	    //return  10		4
 5        } catch (AException e) { //精确捕获异常A	2
 6            e.printStackTrace();
 7        } catch (BException e){  //精确捕获异常B	
 8            e.printStackTrace();
 9        } finally {
10            //一定会执行(释放资源等……)	3
11	    //return -10;	4(最终返回-4 ,取代return 10)
12        }

异常处理 throws/throw 关键

throws 关键字
 throws 声明异常,往外抛出。
 语法:throws ⼦句放在 ⽅法参数列表的右括号之后,⼀个 ⽅法可以声明抛出多个异常, 多个异常之间 ⽤逗号隔开。

1@Test
2    public void readChar() throws IOException, RemoteException {
3        int input = System.in.read();
4    }

throw 关键字
 try catch 中捕获了异常,处理 ⽅法

  • 捕获当前异常。
  • 捕获自己处理然后继续往外部抛异常
 1//方法中使用throw抛出异常,必须在方法签名中使用throws声明抛出的异常类型(编译时异常)
 2    public static void readChar() throws IOException {
 3        try {
 4            int input = in.read();
 5        } catch (IOException e) {
 6            System.out.println("出异常了");//1
 7            throw new IOException("异常信息");
 8        }
 9    }
10   
11    //调用者:自己捕获异常,自己处理。
12    public static void main(String[] args) {
13        try {
14            readChar();
15        } catch (IOException e) {
16           System.out.println("main函数异常");//2
17        }
18    }
19
20    //调用者:继续往外部抛异常
21    public static void main(String[] args) throws IOException {
22            readChar();
23    }

总结
 当抛出(throw)⼀个被检查的异常,我们必须使 ⽤ try-catch 块来处理它,或者在 ⽅法声明中使 ⽤ throws 子句继续往外抛

自定义异常

 JDK 内置的异常不足以满足生产环境的需求,生产环境中会出现各种各样的异常。自定义异常可以让业务更清晰。
 异常都是继承 ⾃ Exception 类,所以我们要自定义的异常也需要继承 Exception 这个基类。

自定义异常类

 1public class UserNotEnoughException extends Exception{
 2    private int code;
 3    private String message;
 4
 5    public UserNotEnoughException(){
 6        super();
 7    }
 8
 9    public UserNotEnoughException(int code, String message) {
10        super(message);
11        this.code = code;
12        this.message = message;
13    }
14
15    public int getCode() {
16        return code;
17    }
18
19    public void setCode(int code) {
20        this.code = code;
21    }
22
23    @Override
24    public String getMessage() {
25        return message;
26    }
27
28    public void setMessage(String message) {
29        this.message = message;
30    }
31}

方法中使用自定异常

 1public static void main(String[] args) {
 2        try {
 3            test();
 4        } catch (UserNotEnoughException e) {
 5            e.printStackTrace();
 6            int code = e.getCode();
 7            String message = e.getMessage();
 8            System.out.println("code="+code + ", msg="+ message);
 9        }
10    }
11
12    public static void test() throws UserNotEnoughException {
13        throw new UserNotEnoughException(-1,"人员不够");
14    }

作者:Soulboy