在我們日常開發中,都不會被允許使用異常捕獲來完成流程控制,比如我們想判斷使用者輸入的是否是數字,可以直接catch一個NumberFormatException異常來判斷;那麼不好意思,你這程式碼一旦有人Review,可能會屌飛你。
可能你會不理解,一臉懵逼,那麼本文將帶你瞭解一下不允許這麼做的原因。
一、流程控制的概念
1.1 定義
流程控制是程式設計中用於指導程式執行順序的一種機制。它允許開發者定義程式中的邏輯分支,使得程式能夠根據不同的條件執行不同的程式碼路徑。
1.2 在程式設計中的作用
流程控制在程式設計中的作用是至關重要的,它允許程式根據不同的條件和輸入做出決策,執行相應的操作。這使得程式能夠靈活地響應使用者輸入、資料狀態和其他執行時情況。
1.3 常見結構
流程控制結構是實現流程控制的語法元素,流程控制語句這裏不展開介紹
二、異常捕獲的概念
異常捕獲,也稱為異常處理,是程式設計中一種用於處理程式執行過程中出現的非預期情況或錯誤的方法。這種機制允許程式在遇到錯誤時,不會導致整個程式崩潰,而是能夠以一種可控的方式對錯誤進行響應和處理。
2.1 定義
異常捕獲通常涉及以下幾個關鍵概念:
2.2 捕獲異常的作用
防止程式崩潰:透過捕獲異常,程式可以避免因為未處理的錯誤而突然終止。
提供錯誤資訊:異常處理可以提供關於錯誤的詳細資訊,幫助開發者或使用者理解問題所在。
資源管理:異常處理機制通常用於確保即使在發生錯誤的情況下,資源(如檔案、網路連線等)也能被正確地釋放或關閉。
控制程式流程:透過異常處理,程式可以在發生錯誤時執行特定的邏輯,如重試操作、記錄錯誤日誌、跳轉到錯誤處理頁面等。
2.3 捕獲異常的目的
2.4 實現方式
異常的捕獲的實現這裏不做追溯
三、目的不同點的比較
維度 | 流程控制 | 異常捕獲 |
---|---|---|
特點 | 預期內的邏輯分支,用於正常的業務邏輯判斷 | 處理非預期情況,用於處理程式執行中的錯誤和異常 |
使用場景 | 正常的業務邏輯判斷,決定程式的執行路徑 | 處理程式中的錯誤和異常,確保程式在出錯時能夠恢復或終止執行 |
執行頻率 | 可能頻繁執行,根據業務邏輯的不同而變化 | 通常較少發生,處理非預期的錯誤和異常情況 |
設計哲學 | 體現程式的正常邏輯,控制程式的執行流程實現業務需求 | 體現程式的健壯性和錯誤容忍度,確保程式在出錯時能夠適當地處理異常情況 |
四、為什麼不應該使用異常作為流程控制
語義清晰性:異常處理應專注於異常情況,而非常規流程。
效能考慮:異常處理的效能成本及其對程式效能的影響。
資源管理:異常處理與資源釋放的關聯,以及不當使用可能導致的問題。
可讀性和可維護性:異常作為流程控制對程式碼可讀性和維護性的影響。
異常的傳播和不可預測性:異常的傳播機制及其對程式流程的影響。
錯誤處理的複雜性:使用異常進行流程控制可能導致的錯誤處理邏輯複雜化。
隱藏錯誤:異常捕獲可能掩蓋真正的問題所在。
違反設計原則:異常捕獲用於流程控制可能違反單一職責原則等設計原則。
五、流程控制與異常捕獲的結合
流程控制和異常捕獲雖然在設計上有不同的目的,但在實際程式設計中,它們有時需要協同工作來實現更加健壯和靈活的程式設計。以下是一些情況和示例,展示如何在保持各自目的清晰的同時合理地結合使用流程控制和異常捕獲:
5.1 預檢查條件以避免異常
在執行可能丟擲異常的操作之前,可以使用流程控制結構來檢查條件,以避免異常的發生。
示例:
public void processFile(String filePath) { // 使用流程控制檢查檔案是否存在,避免IOException if (!fileExists(filePath)) { System.out.println("檔案不存在,無法處理。"); return; } try { // 執行可能丟擲IOException的操作 processFileContent(filePath); } catch (IOException e) { // 處理可能發生的IOException System.out.println("處理檔案時發生錯誤:" + e.getMessage()); } } private boolean fileExists(String filePath) { // 檢查檔案是否存在的邏輯 // ... }
5.2 異常捕獲後的流程控制決策
在捕獲異常後,可以使用流程控制結構來決定後續的程式行為,例如記錄日誌、重試操作或退出程式。
示例:
public void fetchDataFromDatabase() { boolean success = false; for (int attempt = 0; attempt < 3; attempt++) { try { // 嘗試從資料庫獲取資料 data = getDatabaseData(); success = true; break; // 如果成功獲取資料,則退出迴圈 } catch (SQLException e) { // 捕獲資料庫異常,並記錄日誌 System.out.println("資料庫查詢失敗,嘗試次數:" + (attempt + 1)); logError(e); } } if (!success) { System.out.println("多次嘗試後仍未能從資料庫獲取資料。"); } }
5.3 使用異常捕獲來處理預期外的情況
在某些情況下,雖然可以使用流程控制來處理一些條件,但使用異常捕獲來處理那些預期外或不常見的情況可能更為合適。
示例:
public void parseInput(String input) { try { // 嘗試將輸入解析為整數 int number = Integer.parseInt(input); // 執行基於number的邏輯 } catch (NumberFormatException e) { // 輸入不是有效的整數格式 System.out.println("輸入不是有效的數字:" + input); } }
5.4 異常捕獲與資源管理的結合
在需要管理資源(如檔案流、網路連線等)的情況下,可以使用
try-catch-finally
結構來確保資源在異常發生時也能被正確關閉。示例:
public void readFile(String filePath) { InputStream inputStream = null; try { inputStream = new FileInputStream(filePath); // 執行檔案讀取操作 } catch (FileNotFoundException e) { // 檔案未找到異常處理 System.out.println("檔案未找到:" + filePath); } finally { // 無論是否發生異常,都確保關閉資源 if (inputStream != null) { try { inputStream.close(); } catch (IOException e) { // 資源關閉異常處理 System.out.println("關閉檔案流時發生錯誤:" + e.getMessage()); } } } }
六、總結
事物是發展變化的,一個東西在這個場景不可用,在別的場景用起來就非常合理;沒有一個技術方案是萬用金的,作為一個技術人,講究的就是一個靈醒,當然,如果你寫的一個程式碼自己覺得很牛逼,領導看不慣,那咱說不過改就好了。