一篇文章詳解Java異常處理
Java異常的三種分類
- 受檢異常(Checked Exceptions):最具代表性的是用戶錯誤和問題引起的異常,程序員無法遇見,這些異常在編譯時強制要求進行處理,比如打開一個不存在的文件。如果一個方法可能會引發(fā)受檢異常,要么在方法簽名中使用throws子句聲明,要么使用try-catch塊捕獲并處理這些異常。例如,IOException就是一個受檢異常,它需要在代碼中進行顯式處理。
- 運行時異常(Runtime Exceptions):這些異常是RuntimeException類及其子類的實例。與受檢異常不同,編譯時會被忽略,運行時異常不需要顯式地捕獲或聲明。常見的運行時異常包括NullPointerException、ArrayIndexOutOfBoundsException和ArithmeticException等。
- 錯誤(Errors):錯誤通常指示了嚴重的問題,大多數情況下是程序無法處理的。與異常不同,錯誤通常不應該被捕獲和處理。常見的錯誤包括StackOverflowError和OutOfMemoryError等。
異常體系結構
Java的異常體系結構是基于Throwable類的,java.lang.Throwable
作為所有異常的超類
Error
Error
類是Java編程語言中表示嚴重問題的基類之一。
在Java中,Error
對象表示的是系統(tǒng)級的錯誤和運行時環(huán)境的問題,通常由Java虛擬機(JVM)生成和拋出。
與一般的異常不同,Error
及其子類通常表示虛擬機自身的問題,而不是應用程序的問題。
一些常見的Error
子類包括:
- OutOfMemoryError:當JVM無法再分配內存時拋出,表示內存耗盡。
- StackOverflowError:當方法調用的層級太深,導致??臻g耗盡時拋出。
- NoClassDefFoundError:當JVM或ClassLoader無法找到所需的類定義時拋出。
- InternalError:表示JVM內部發(fā)生了嚴重錯誤。
Exception
Exception
類是Java編程語言中表示一般意外情況或錯誤的基類之一。
在Java中,Exception
及其子類通常用于表示程序運行過程中可能發(fā)生的各種異常情況。
Exception
類的直接子類主要分為兩種:
- Checked Exception:這些異常必須在代碼中進行處理,要么通過try-catch塊捕獲和處理,要么通過throws子句聲明向上傳播。
- RuntimeException:這些異常通常是由程序錯誤引起的,不要求在代碼中強制處理。
一些常見的 Checked Exception:
- IOException:用于表示輸入輸出操作中可能發(fā)生的異常情況,如文件未找到、文件權限問題等。
- SQLException:用于表示與數據庫訪問相關的異常,例如連接問題、查詢問題等。
- ClassNotFoundException:用于表示在運行時找不到特定類的異常。
- FileNotFoundException:指示嘗試打開指定文件名的文件失敗。
- ParseException:用于表示解析操作中可能發(fā)生的異常,例如日期解析錯誤。
- NoSuchMethodException:指示嘗試訪問不存在的方法時發(fā)生的異常。
一些常見的 RuntimeException:
- NullPointerException:當應用程序試圖在要求使用對象的地方使用 null 時,拋出該異常。
- ArrayIndexOutOfBoundsException:用于指示數組索引超出范圍。
- ArithmeticException:表示在算術運算中發(fā)生的異常情況,例如除以零。
- IllegalArgumentException:指示向方法傳遞了一個不合法或不正確的參數。
- IllegalStateException:表示對象的狀態(tài)不適合請求的操作。
- ClassCastException:當試圖將對象強制轉換為不是實例的子類時,拋出該異常。
異常處理機制
1、try-catch塊:try
用于包裹可能會引發(fā)異常的代碼塊,catch
用于捕獲并處理特定類型的異常。如果 try
塊中的代碼引發(fā)了異常,Java 將會跳到匹配的 catch
塊中執(zhí)行相應的處理代碼。
try { // 可能引發(fā)異常的代碼 } catch (ExceptionType e) { // 處理異常的代碼 }
2、finally塊:finally
塊中的代碼總是會被執(zhí)行,無論是否發(fā)生異常。通常用于確保資源的釋放,如關閉文件或網絡連接。
try { // 可能引發(fā)異常的代碼 } catch (ExceptionType e) { // 處理異常的代碼 } finally { // 無論是否發(fā)生異常都會執(zhí)行的代碼 }
3、throws關鍵字:throws
用于在方法聲明中指定可能會拋出的異常,將異常的處理責任交給調用者。這就是告訴調用者,調用這個方法時,需要考慮到可能會拋出的異常情況。
void someMethod() throws SomeException { // 方法可能拋出 SomeException }
void readFile() throws IOException { // 讀取文件的代碼 }
在這個例子中,readFile
方法聲明了可能會拋出 IOException
異常。當其他代碼調用 readFile
方法時,調用者需要考慮到可能會出現(xiàn) IOException
異常的情況。
4、throw關鍵字:throw
用于手動拋出一個異常。這意味著當程序執(zhí)行到 throw
語句時,會創(chuàng)建一個異常對象并將其拋出。這個異??梢允?Java 標準庫中已經定義好的異常類型,也可以是你自己定義的異常類型。
if (someCondition) { throw new SomeException("Error message"); }
舉個例子,假設你正在編寫一個函數,需要檢查傳入的參數是否滿足某些條件,如果條件不滿足,你可以使用 throw
拋出一個異常來中斷程序的執(zhí)行并給出相應的提示或錯誤信息。
void checkAge(int age) { if (age < 0) { throw new IllegalArgumentException("Age cannot be negative"); } }
在這個例子中,如果傳入的年齡是負數,throw
語句將會創(chuàng)建一個 IllegalArgumentException
異常對象并將其拋出。
5、自定義異常:可以通過擴展 Exception
類或其子類來創(chuàng)建自定義異常類,以便應用程序可以根據特定的需求創(chuàng)建和使用異常類型。
如果不加throws MyException
會報錯,這是因為:在Java中,如果一個方法可能拋出已檢查異常(checked exception),但沒有使用try-catch
塊捕獲該異常,也沒有使用throws
子句將該異常傳播出去,編譯器會報錯。
幾種異常處理方式的區(qū)別:
throw
用于手動拋出異常,throws
用于聲明可能會拋出的異常類型,而try-catch
用于實際處理異常情況。throw
和try-catch
是用于實際處理異常的,而throws
是在方法聲明中指明可能會拋出的異常類型。
舉例:
import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; public class FileHandlingExample { public static void main(String[] args) { BufferedReader reader = null; try { reader = new BufferedReader(new FileReader("example.txt")); String line = reader.readLine(); int number = Integer.parseInt(line); System.out.println("Read number: " + number); } catch (FileNotFoundException e) { System.err.println("File not found: " + e.getMessage()); } catch (NumberFormatException e) { System.err.println("Invalid number format: " + e.getMessage()); } catch (IOException e) { System.err.println("IOException: " + e.getMessage()); } finally { try { if (reader != null) { reader.close(); } } catch (IOException e) { System.err.println("Error while closing the reader: " + e.getMessage()); } } } }
在這個例子中,我們嘗試打開一個文件并讀取其中的內容。在 try
塊中,我們打開文件并嘗試讀取文件中的一行內容,并將其轉換為整數。在 catch
塊中,我們分別捕獲了 FileNotFoundException
(文件未找到)、NumberFormatException
(無效的數字格式)和 IOException
(輸入輸出異常)。
在 finally
塊中,我們確保關閉了文件讀取器,即使在 try
或 catch
塊中發(fā)生了異常,也會執(zhí)行這一步。這是非常重要的,因為它確保資源得到了正確的釋放。
Java 編譯器會按照 catch
塊的順序來匹配異常,而一旦找到了匹配的 catch
塊,后續(xù)的 catch
塊將不再執(zhí)行。 因此,如果將最一般的異常類型放在最前面,那么可能會導致后續(xù)的 catch
塊永遠無法執(zhí)行。
在前面提供的示例代碼中,我們先捕獲了 FileNotFoundException
,然后是 NumberFormatException
,最后是 IOException
。這是符合最佳實踐的順序。
如果按照相反的順序,即先捕獲 IOException
,然后是 NumberFormatException
,最后是 FileNotFoundException
,那么由于 IOException
是 FileNotFoundException
和 NumberFormatException
的父類,IOException
的 catch 塊將會捕獲到所有這些異常,而后續(xù)的 catch 塊將無法執(zhí)行。
因此,捕獲異常時應該遵循從最具體的異常類型到最一般的異常類型的順序,以確保程序能夠按預期進行異常處理。
書寫異常處理語句的快捷鍵:ctrl+alt(option)+T
手動結束程序語句:
實際使用中的經驗總結:
- 處理運行時異常時,采用邏輯去合理規(guī)避同時輔助try-catch處理
- 在多重catch塊后面,可以加上一個catch(Exception)來處理可能會被遺漏的異常
- 對于不確定的代碼,也可以加上try-catch處理異常
- 盡量去處理異常,切忌僅使用printStackTrace()打印輸出
- 具體處理異常,根據業(yè)務需求和異常類型的不同決定
- 盡量添加finally釋放占用的資源(IO、Scanner)
總結
到此這篇關于一篇文章詳解Java異常處理的文章就介紹到這了,更多相關Java異常處理內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
SpringMVC使用ResponseEntity實現(xiàn)文件上傳下載
這篇文章主要為大家介紹了SpringMVC使用ResponseEntity實現(xiàn)文件上傳下載,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-05-05springsecurity6配置自定義路徑身份認證的實現(xiàn)
本文主要介紹了springsecurity6配置自定義路徑身份認證的實現(xiàn),通過使用自定義的AuthorizationManager和MyService,可以實現(xiàn)更靈活的訪問控制,感興趣的可以了解一下2025-03-03Spring Boot中使用 Spring Security 構建權限系統(tǒng)的示例代碼
本篇文章主要介紹了Spring Boot中使用 Spring Security 構建權限系統(tǒng)的示例代碼,具有一定的參考價值,有興趣的可以了解一下2017-08-08