天天看點

Java中異常處理小細節一、前言二、來龍去脈三、總結

一、前言

Java中異常分為兩種:一種是基于Error的,一種是基于Exception的。其兩者都是繼承自Throwable;其中Error錯誤一般都是不可恢複的錯誤,比如系統崩潰、虛拟機錯誤,記憶體空間不足、類定義找不到、方法調用棧溢出等;而Exception錯誤則是我們經常使用來做業務異常攔截的;對于Error類型錯誤一般由于是不可恢複錯誤,是以沒必要catch掉,但是凡事都有例外...

二、來龍去脈

如下代碼,service()方法用來模拟業務服務,代碼比較簡單,一般下我們是首先建立一個傳回對象,然後在try塊中執行業務,然後設定結果;執行異常後在catch使用Exception類型捕獲異常,然後設定result傳回值為false。最後傳回結果,這個代碼看起來很正常:

public class Test {

    // 業務伺服器提供的服務
    public static Result service() {

        // 1.建立傳回對象
        Result result = new Result();
        result.setSucess(true);

        // 2.執行業務
        try {
            // 2.1執行業務,設定傳回值 .....
            ...
            result.setData("ok");

        } catch (Exception e) {
            // 2.2比如業務異常則設定為false,并且傳回異常資訊
            result.setSucess(false);
            result.setCode("biz-error1");
        }
        // 3.傳回結果
        return result;

    }

    public static void main(String[] args) throws InterruptedException, ClassNotFoundException {

        Executor executor = Executors.newFixedThreadPool(5);
        executor.execute(() -> {
            System.out.println(JSON.toJSONString(service()));
        });

        executor.shutdown();

    }
}           

複制

當service()服務線上程池裡面執行時候,并且service()方法裡面抛出NoClassDefFoundError異常後,我們會看不到System.out.println(JSON.toJSONString(service()));輸出結果,也不知道異常NoClassDefFoundError跑到哪裡去了,這非常不利于排查問題。

由于NoClassDefFoundError是繼承自Error,而Error繼承自Throwable,是以我們有必要在加一個catch塊來捕獲Throwable異常:

public static Result service() {

        // 1.建立傳回對象
        Result result = new Result();
        result.setSucess(true);

        // 2.執行業務
        try {
            // 2.1執行業務,設定傳回值 .....
            if (true) {
                throw new NoClassDefFoundError("calss def can not found");
            }

            result.setData("ok");

        } catch (Exception e) {
            // 2.2比如業務異常則設定為false,并且傳回異常資訊
            result.setSucess(false);
            result.setCode("biz-error1");
        } catch (Throwable e) {
            // 2.3比如不可恢複的異常,比如NoClassDefFoundError,則設定為false,并且傳回異常資訊
            result.setSucess(false);
            result.setCode("sys-error1");
            System.out.println(e.getLocalizedMessage());

        }

        // 3.傳回結果
        return result;

    }           

複制

當然要想實作簡單捕獲線程中抛出的異常也可以實作UncaughtExceptionHandler來捕獲。

三、總結

雖然Error類型的錯誤是不可恢複錯誤,但是有時候我們還是需要顯示的捕獲并列印日志,以便問題排查;另外比如NoClassDefFoundError類型錯誤,可以隻是應用中部分服務不可用,但是其他子產品服務是可用的,是以這時候我們還是要理會的。