目录

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 的元素代表栈顶,最后 ⼀个元素代表 ⽅法调 ⽤堆栈的栈底。
package com.javase.demo;

import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest(classes = DemoApplication.class)
class DemoApplicationTests {

    @Test
    public void tryCatchTesting() {
        try {
            int result = 2/0;
            System.out.println(result);
        } catch (Exception e) {
            e.printStackTrace();//打印错误的堆栈信息。可以看到错误原因和所在位置。
            String msg = e.getMessage();
            StackTraceElement[] arr = e.getStackTrace();
        }
    }
}

//java.lang.ArithmeticException: / by zero
//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
try {
            //发生异常的代码(此处中断,产生异常,进入catch代码块)1
	    //其他代码(不会执行)	
	    //return  10		4
        } catch (AException e) { //精确捕获异常A	2
            e.printStackTrace();
        } catch (BException e){  //精确捕获异常B	
            e.printStackTrace();
        } finally {
            //一定会执行(释放资源等……)	3
	    //return -10;	4(最终返回-4 ,取代return 10)
        }

异常处理 throws/throw 关键

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

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

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

  • 捕获当前异常。
  • 捕获自己处理然后继续往外部抛异常
//方法中使用throw抛出异常,必须在方法签名中使用throws声明抛出的异常类型(编译时异常)
    public static void readChar() throws IOException {
        try {
            int input = in.read();
        } catch (IOException e) {
            System.out.println("出异常了");//1
            throw new IOException("异常信息");
        }
    }
   
    //调用者:自己捕获异常,自己处理。
    public static void main(String[] args) {
        try {
            readChar();
        } catch (IOException e) {
           System.out.println("main函数异常");//2
        }
    }

    //调用者:继续往外部抛异常
    public static void main(String[] args) throws IOException {
            readChar();
    }

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

自定义异常

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

自定义异常类

public class UserNotEnoughException extends Exception{
    private int code;
    private String message;

    public UserNotEnoughException(){
        super();
    }

    public UserNotEnoughException(int code, String message) {
        super(message);
        this.code = code;
        this.message = message;
    }

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    @Override
    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

方法中使用自定异常

public static void main(String[] args) {
        try {
            test();
        } catch (UserNotEnoughException e) {
            e.printStackTrace();
            int code = e.getCode();
            String message = e.getMessage();
            System.out.println("code="+code + ", msg="+ message);
        }
    }

    public static void test() throws UserNotEnoughException {
        throw new UserNotEnoughException(-1,"人员不够");
    }

作者:Soulboy