簡體   English   中英

避免使用try-catch語句的充分理由

[英]Good reasons to avoid using try-catch statements

示例#1:

try { fileChooser.setSelectedFile(new File(filename)); }
catch (NullPointerException e) { /* do nothing */ }

示例#2:

if (filename != null)
    fileChooser.setSelectedFile(new File(filename));

出於性能或穩定性(或任何其他原因),#1本質上是不好的,還是只是有點不同? 這不是一個很好的例子,因為#1優於#2沒有優勢,但在不同情況下可能存在(例如,可讀性提高,代碼行數減少等)。


編輯:共識似乎是#1是禁忌。 最受歡迎的原因:開銷

此外, @ Raph Levien有一個很好的見解:

避免#1的一個原因是它會中毒你使用異常斷點的能力。 正常運行的代碼永遠不會故意觸發空指針異常。 因此,將調試器設置為每次發生時都停止是有意義的。 在#1的情況下,您可能會例行地獲得此類異常。 除其他正當理由外,還有潛在的性能影響。

另外, 請參閱鏈接以獲取更多深度。

絕對#2是一個更好的選擇。 不應將異常處理用作程序控制流中的構造。 應該使用例外來處理不受程序員控制的情況。 在此示例中,您可以檢查fileChooser是否為null,以便您可以控制。

例外會帶來一定的開銷。 如果可以避免它們,在這種情況下,只需檢查一個null,那將是首選。

正如其他人所說,使用Exceptions進行流量控制通常也是不好的做法。 有關這為什么不好的詳細解釋,請查看此內容。

以下是該答案的簡短介紹:

例外基本上是非本地goto語句,具有后者的所有后果。 使用流控制的異常違反了最不驚訝的原則,使程序難以閱讀(記住程序首先是為程序員編寫的)。

  • 不要使用Exception來控制邏輯流程。
  • 永遠不要吞下異常。 #1違反了它 - 你永遠不會知道NPE是來自fileChooser==null還是fileName==null

如果程序在邏輯上允許空值,請對其進行測試。 否則使用例外。 例外是為了處理異常情況(驚喜!),不應該用於程序邏輯。

避免#1的一個原因是它會中毒你使用異常斷點的能力。 正常運行的代碼永遠不會故意觸發空指針異常。 因此,將調試器設置為每次發生時都停止是有意義的。 在#1的情況下,您可能會例行地獲得此類異常。 除其他正當理由外,還有潛在的性能影響。

我會選擇#3選項 - 如果將filename作為函數參數傳遞,請在注釋中添加一個不允許使用空文件名的注釋。 然后假設文件名永遠不為空:

fileChooser.setSelectedFile(new File(filename));

如果某個白痴(或你,<3)忽略了你的評論並且''確實''傳遞了一個null,他將得到一個NullPointerException並且必須解決問題。

在客戶端代碼中,始終通過初始化或將fileName默認為空字符串來確保不傳遞空值。

我一直在避免使用和接受空值一段時間,而且我的代碼更清晰,因為它已經沒有那么多的空檢查了。 仍然存在的唯一空檢查是我稱為可能返回null的第三方代碼的那些。

(咆哮:當然,我必須反編譯所說的第三方代碼並確定我自己,考慮到文檔不存在或者沒有記錄它可能返回null)

在以下情況中,您的兩個示例在語義上不相同:

  • fileChoosernull
  • setSelectedFile拋出一個NullPointerException (被授予,這個特定的方法不會發生這種情況,但一般情況下,setter很可能將東西存儲在某個其他對象中,如果未初始化該另一個對象的引用,它將拋出)
  • new File()拋出NullPointerException ,原因不是filenamenull

可能, /* do nothing */僅用於filename為null的情況,但現在也隱藏其他情況,而良好的異常處理會允許這些異常冒泡調用堆棧,提醒您存在和原因你會發現很難找到的錯誤。

我發現這是比性能更令人信服的理由,因為浪費的程序員時間比浪費的cpu時間貴得多。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM