一切皆对象,异常也同样

   认识异常

  异常基础

  所谓的异常,就是程序按照正常执行逻辑走着走着遇到问题,崴了脚或闪了腰,已经没法再继续走下去了。怎么办呢?就像有病要治病同样,有异常就得处理异常。Java提供了基本的语法来处理异常:一中是throw(s)语法,叫抛异常;一种是try-catch-finally语法,叫作捕获异常。Java是面向对象的,在Java的世界里一切皆是对象,因此异常天然也被当作是一种对象,当异常发生,就是建立了一个异常对象,咱们使用两种语法来处理异常对象就好了,语法也很简单,下面只简单示例:程序员

public class Test {

    //继续外抛异常
    public void test1() throws FileNotFoundException {
        new FileInputStream("D://test.txt");
    }

    //本身捕获异常
    public void test2() {
        try {
            new FileInputStream("D://test.txt");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }finally{
            //无论异常发没发生都总会执行的部分,一般用来处理收尾工做,入内存清理,关闭流等等
        }
    }

    //本身主动建立异常对象并抛出
    public void test3() throws Exception {
        throw new Exception("抛出异常");
    }

}

  这里很基础,仍是说三点:ide

  ① 最好从英文词性上区分throw和throws两个关键字。前者是动词,表明抛出,很明显是用在方法内部,执行异常对象的抛出动做;后者是名词,用在方法后面,用来声明方法执行可能抛出的一个或多个异常,多个异常之间用逗号隔开;测试

  ② finally块不是必须的,除非业务中有必需要执行的部分;若是有finally块,那该部分语句不管方法是否发生异常甚至中途执行return终止方法,该部分都会获得执行;finally块中不能使用return,会形成异常丢失;this

  ③ 若是你对异常是该抛出和本身处理举棋不定,那布衣博主告诉你一个原则:该背锅背锅,不能背就甩锅!是的,异常和平常中的甩锅行为相似。当别人向你甩来的锅若是你能背,那就接住大胆背锅处理异常,否则就甩锅吧给上层调用者处理。编码

  异常体系

  打开JDK API 文档,找到 lang包中 Throwable类,这就是Java异常的祖宗类了。你会发现异常家族体系至关庞大,但大而不乱,由于这祖宗也就两个直接子类 Error 和 Exception。Error 一般指系统错误,程序员无需关心;Exception才是须要抛出或者捕获的异常的基类,其下有不少子类孙类,支系繁茂。对于Exception类型异常,又分了编译期异常和运行时异常两大类,前者是在编码阶段必须处理(捕获或者抛出)的异常类型,不处理程序没法正常编译;后者不用主动处理,一般是程序逻辑上的异常,在程序运行时由虚拟机抛出。只需记住以下谱系图便可:spa

  自定义异常

  简单封装

  Java标准类库中的异常虽然已经不少了,可是那是标准库中通用的异常状况,不一样项目会有不一样的业务逻辑,这就须要咱们根据本身的业务逻辑来定义、处理本身的异常。最好的自定义方式是从跟本身业务处理意思最接近的异常类继承,好比定义运行时异常能够继承RuntimeException,定义IO异常能够继承IOException。不过对异常情形限定得太窄其实也没有必要了,直接继承异常基类Exception便可:code

public class MyException extends Exception {
    public MyException() {
        super();
    }

    public MyException(String message) {
        super(message);
    }

    public MyException(String message, Throwable cause) {
        super(message, cause);
    }
}

  这样简单的继承,只是屏蔽了底层的具体异常类,对外暴露的是和本身业务相关的语义化的异常类名而已,功能依旧是父类异常的功能。这样的自定义异常显然功能太父类化了。更多的状况下,咱们但愿异常类能有比父类更完备的功能,以帮助程序向客户端调者反馈更友好的信息。这个时候要跳出异常的字面意思去理解Java的异常机制,不能简单的认为异常就是发生了不想看到的错误,而是把异常当作一种控制流,是程序流程处理的一部分,控制着个人程序在状况1 时走哪一步,在状况2下又该执行哪一步。好比经过JNA调用底层动态库获取硬件信息,因为程序运行的不可预见性,Java程序员和底层语言开发者之间会根据返回值约定一些异常情形,好比 0 表明什么,1 表明什么,诸如此类:对象

    public void func(int result) throws MyException1 ,MyException2,MyException3{
        switch (result){
            case 1:throw new MyException1();
            case 2:throw new MyException2();
            case 3:throw new MyException3();
            ...
        }
    }

  像上面这种,利用穷举的方式写代码确定是很不明智的,更多的时候,咱们会采用枚举与自定义异常相结合的方式,来处理异常的流程控制,以更好的发挥自定义异常的自定义做用。blog

  异常与枚举

   先定义约定的异常情形枚举:继承

//异常状态枚举
public enum ErrorCode {
    SUCCESS(0, "成功"),
    NOTFOUND(1, "未找到验证设备"),
    READFAIL(2, "读取验证设备失败"),
    OVERDUE(3, "验证设备已过时"),
    UNKNOWN(4, "未知缘由的失败");

    int code;
    String msg;

    ErrorCode(int code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    public int getCode() {
        return code;
    }

    public String getMsg() {
        return msg;
    }

    //根据状态码获取状态信息
    public static ErrorCode getErrorCode(int code) {
        for (ErrorCode errorCode : values()) {
            if (errorCode.code == code) {
                return errorCode;
            }
        }
        return null;
    }

    @Override
    public String toString() {
        return "ErrorCode{" +
                "code=" + code +
                ", msg='" + msg + '\'' +
                '}';
    }
}

  再定义本身的异常类:

public class LibException extends Exception {

    private int code;
    private ErrorCode errorCode;


    public ErrorCode getErrorCode() {
        return errorCode;
    }


    LibException(int code) {
        this.code = code;
        this.errorCode = ErrorCode.getErrorCode(code);
    }

    public int getCode() {
        return code;
    }

    public LibException(String message) {
        super(message);
    }

    public LibException(String message, Throwable cause) {
        super(message, cause);
    }

}

    经过枚举和自定义异常的结合,便能在程序中动态的根据错误码反馈给上层调用者友好的异常信息。测试:

public class Test {
    public static void chenbenbuyi(int result) throws LibException {
        if(result>=0&&result<=4)throw new LibException(result);
        System.out.println("result: "+result);
    }

    public static void main(String[] args) {
        try {
            chenbenbuyi(3);
        } catch (LibException e) {
                System.err.println("错误码:"+e.getCode()+" 错误信息:"+e.getErrorCode().getMsg());
        }
    }
}

  友好输出反馈:

相关文章
相关标签/搜索