Java異常處理最佳實踐

總結一些Java異常的處理原則java

Java異常處理最佳實踐

不要忘記關閉資源

在finally裏關閉資源jvm

public void readFile() {
    FileInputStream fileInputStream = null;
    File file = new File("./test.txt");
    try {
        fileInputStream = new FileInputStream(file);
        int length;
        byte[] bytes = new byte[1024];
        while ((length = fileInputStream.read(bytes)) != -1) {
            System.out.println(new String(bytes, 0, length));
        }
    } catch (FileNotFoundException e) {
        logger.error("找不到文件", e);
    } catch (IOException e) {
        logger.error("讀取文件失敗", e);
    } finally {
        if (fileInputStream != null) {
            try {
                fileInputStream.close();
            } catch (IOException e) {
                logger.error("關閉流失敗", e);
            }
        }
    }
}

用try-with-resource關閉資源日誌

public void readFile2() {
    File file = new File("./test.txt");
    try(FileInputStream fileInputStream = new FileInputStream(file)) {
        int length;
        byte[] bytes = new byte[1024];
        while ((length = fileInputStream.read(bytes)) != -1) {
            System.out.println(new String(bytes, 0, length));
        }
    } catch (FileNotFoundException e) {
        logger.error("找不到文件", e);
    } catch (IOException e) {
        logger.error("讀取文件失敗", e);
    }
}

使用描述性消息拋出異常

指定具體的異常

  • 用NumberFormatExcepton而不是Exception,這樣能更快的定位問題
  • NumberFormatException 是運行時異常
public void numberFormat() {
    try {
        String year = "2018";
        System.out.println(Integer.parseInt(year));
    } catch (NumberFormatException e) { // 捕獲NumberFormatExceptoin而不是Exception
        logger.error("年份格式化失敗", e); // 描述一下異常
    }
}

給異常加註釋

// 自定義一個異常
class NotFoundGirlFriendException extends Exception {
    public NotFoundGirlFriendException(String message) {
        super(message);
    }
}

/**
 *
 * @param input
 * @throws NotFoundGirlFriendException input爲空拋出異常
 */
public void doSomething(String input) throws NotFoundGirlFriendException {
    if (input == null) {
        throw new NotFoundGirlFriendException("出錯了");
    }
}

優先捕獲具體異常

public int getYear(String year) {
    int retYear = -1;
    try {
        retYear = Integer.parseInt(year);
    } catch (NumberFormatException e) {
        logger.error("年份格式化失敗", e);
    } catch (IllegalArgumentException e) {
        logger.error("非法參數", e);
    }
    return retYear;
}

不要捕獲Throwable

  • Throwable是全部異常和錯誤的父類,會把error捕獲
  • error是那些沒法恢復的jvm錯誤,eg:StackOverflowError和OutOfMemoryError
public void test6() {
    try {
    } catch (Throwable e) {
    }
}

不要忽略異常

public void test7() {
    try {

    } catch (NumberFormatException e) {
        logger.error("即使你認爲不可能走到這個異常,也要記錄一下", e);
    }
}

捕獲和拋出只選擇一種

  • 不要同時記錄並拋出異常,會致使相同錯誤日誌輸出屢次
public void foo() {
    try {
        new Long("xyz");
    } catch (NumberFormatException e) {
        logger.error("字符串格式化成Long失敗", e);
        throw e;
    }
}

包裝異常不要丟棄原始異常

class MyBusinessException extends Exception {
    public MyBusinessException(String message) {
        super(message);
    }
    public MyBusinessException(String message, Throwable cause) {
        super(message, cause);
    }
}

public void wrapException(String id) throws MyBusinessException {
    try {
        System.out.println(Long.parseLong(id));
    } catch(NumberFormatException e) {
        throw new MyBusinessException("ID格式化失敗", e);
    }
}

參考

Java 異常處理最佳實踐(2018)code

相關文章
相關標籤/搜索