陷阱 - 使用正常流程控制的異常

有一些 Java 專家不會背誦的口頭禪:

“異常情況只應用於特殊情況。”

(例如: http//programmers.stackexchange.com/questions/184654

其實質是使用異常和異常處理來實現正常的流控制是一個壞主意(在 Java 中)。例如,比較這兩種處理可能為 null 的引數的方法。

public String truncateWordOrNull(String word, int maxLength) {
    if (word == null) {
        return "";
    } else {
        return word.substring(0, Math.min(word.length(), maxLength));
    }
}

public String truncateWordOrNull(String word, int maxLength) {
    try {
        return word.substring(0, Math.min(word.length(), maxLength));
    } catch (NullPointerException ex) {
        return "";
    }
}

在這個例子中,我們(通過設計)處理 wordnull 的情況,好像它是一個空單詞。這兩個版本使用傳統的 if … else 和或者 try … catch 來處理 null 。我們該如何決定哪個版本更好?

第一個標準是可讀性。雖然可讀性難以客觀量化,但大多數程式設計師都同意第一版的基本含義更容易辨別。實際上,為了真正理解第二種形式,你需要明白 NullPointerExceptionString.substring 方法不能丟擲 NullPointerException

第二個標準是效率。在 Java 8 之前的 Java 版本中,第二個版本比第一個版本慢很多(數量級)。特別是,異常物件的構造需要捕獲和記錄堆疊幀,以防萬一需要堆疊跟蹤。

另一方面,在許多情況下,使用異常比使用條件程式碼處理異常事件更具可讀性,更高效和(有時)更正確。實際上,在極少數情況下有必要將它們用於非特殊事件; 即相對頻繁發生的事件。對於後者,值得研究減少建立異常物件的開銷的方法。