2011-05-16 40 views
0

考慮以下代碼:最好在進程之前進行驗證,或者只是引發異常?

x = Repo.GetX(13); 
Services.Process(x); 

我可以檢查x是處理之前空,我也可以有Services.Process()拋出一個異常,如果X是零和使用try/catch塊。

哪種方法更可取?

(或者我應該都做,只是在x變成空不知何故從其檢索點處理它的例外情況?)

回答

1

如果你試圖決定之間:

x = Repo.GetX(13); 
try { 
    Services.Process(x); 
} catch (NullPointerException) { 
    System.err.println('x is NULL'); 
} 

x = Repo.GetX(13); 
if (x != NULL) { 
    Services.Process(x); 
} else { 
    System.err.println('x is NULL'); 
} 

然後意識到他們並不意味着同樣的事情。第一個捕獲任意Process引發的空指針異常。第二個僅處理x本身爲NULL的情況 - 如果Process確實爲x.foo().bar(),並且x.foo()返回NULL,則不處理它。

您應該根據您可以處理的錯誤來決定兩者之間的關係。

Services.Process在案,以拋出NullPointerException當且僅當x是空的情況下,使(假設我們相信文檔)兩個都意味着同樣的事情,那麼我會做第二個。這樣,如果文檔處於謊言狀態,並且Services.Process中存在一個導致其他情況的錯誤,那麼我們不會錯誤地處理/報告例外​​情況,就好像x事實上不是NULL一樣。

所以,漁獲物和在兩種情況下抑制異常:

  1. 你知道什麼(樣的事情)導致了錯誤,你知道你可以處理這種情況並繼續不分。
  2. 保護程序或環境中的某些相當外層的代碼,如事件循環,以防意外故障。理想情況下,這應該導致廣泛的日誌記錄,因爲系統無法做到您所期望的(可能是由於缺乏資源或未滿足的依賴關係),或者某處的代碼中存在錯誤。

不要捕捉,只是因爲你知道一個情況可能導致的異常,就可以搞定,當相同的異常可能會被拋出其他原因。我想你可以這樣做:

x = Repo.GetX(13); 
try { 
    Services.Process(x); 
} catch (NullPointerException) { 
    if (x == NULL) { 
     System.err.println('x is NULL'); 
    } else { 
     throw; 
    } 
} 

但在我看來,不必要的冗長在這種情況下:因爲我們可以提前檢查x是否爲空,我們不妨。存在這樣的情況,不過,在那裏你趕上一個例外,因爲這是不可能的,或只是愚蠢的嘗試提前預測是否會發生與否:

String s = Rep.GetString(13); 
try { 
    f = Float.parseFloat(s); 
    System.out.println('is a number'); 
} catch (NumberFormatException) { 
    System.out.println('not a number'); 
} 

我們可能檢查s是否是之前調用一個有效的數字parseFloat,但基本上會做兩次相同的工作 - 檢查一個字符串是一個有效的float與實際轉換它幾乎相同。因此,理解這個例外是有道理的 - 我們知道它意味着什麼,我們知道該怎麼做,我們無法真實地阻止它發生。

(或者你可以使用DecimalFormat.parse,不扔在所有)

0

遠東更好地檢查。異常處理通常很昂貴。

+0

只要這個代碼不會在一個巨大的循環中運行,性能不應該被考慮。如果它確實運行在一個緊密的循環中,那麼應該進行測試,並根據那些實現進行調整。 – 2011-05-16 11:06:48

+0

當「特殊」情況很常見時,異常處理通常很昂貴*。如果發生數千次中的一次,跳過檢查並拋出異常實際上可能會更快。正如另一個答案所述,*取決於*。除了表演,還有其他一些事情需要擔心。 – cHao 2011-05-16 11:08:36

1

像往常一樣,這種問題的正確答案是:這取決於。

如果可能,最好的方法是定義一個執行這種檢查的邊界。邊界內的所有東西都可以依賴於所有被很好地初始化的東西。如果還是空着的話,用NPE炸燬是非常合適的。

在嘗試執行實際工作之前,通常要檢查前提條件,以使代碼更簡潔。

如果你不能在你的系統中建立這些邊界,問題是:當x爲NULL並且沒有處理結果異常時會發生什麼,當你不處理它時你有什麼選擇?

在許多情況下,你無論如何都不能做太多的事情,然後讓異常進入調用堆棧直到ui(或者服務接口或其他)就可以了。

但是有時用空參數調用進程會摧毀一塊硬件,殺死一個病人或者以其他方式非常噁心。在這種情況下:請在潛在的有害行爲之前檢查。

0

應該使用異常處理來處理異常。

如果你的東西x不應該爲空使用try/catch語句。如果x將在某些情況下爲空使用和if語句。

相關問題