標籤:
異常處理的思想是,當應用程式處於異常時,它可以聲明這種異常;然後這種異常將被捕獲到並得到妥善地處理,從而避免出現嚴重後果。所謂異常,是值與程式的正常運行邏輯相違背的非正常事件,比如,讀取檔案內容時,檔案不存在;或者說對數組進行操作時,數組下標越界等等。而使用者登入時口令驗證失敗這種情況不能算作異常,因為它是驗證程程式正常運行邏輯的一部分。
一、異常階層與分類
Java中的異常階層如所示:
Error類階層描述了Java運行時系統的內部錯誤和資源耗盡錯誤。對於這種錯誤應用程式是無能為力的,因此應用程式不應該拋出這種類型的對象。
Exception階層分解為兩個分支:一支派生於RuntimeException,它表示由程式錯誤導致的異常。比如null 指標、數組越界、錯誤的類型轉換等等。
另一個分支表示程式本身沒有問題,出問題的是IO讀寫等外部操作,比如在檔案尾部讀取資料、開啟了錯誤的URL等等。
Java語言規範將派生幹Error類或RuntimeException類的所有異常稱為未檢查(unchecked) 異常,所有其他的異常稱為已檢查(checked)異常。編譯器將核査是否為所有的已檢査異常提供了異常處理器。
二、聲明已檢查異常
根據異常規範,方法應該在首部聲明所有可能拋出的異常。然而未檢査異常要麼不可控制(Error), 要麼就應該避免發生(RuntimeException)。因此,規定方法必須對所有可能拋出的已檢查異常進行聲明,否則無法通過編譯。
那麼,我們如何知道一個方法究竟存在哪些已檢查異常呢?不用擔心,編譯器能夠對我們進行提示。當方法調用了可能拋出異常的方法時,eclipse將自動警示,如:
如果不按照提示進行修改則程式無法通過編譯。
三、拋出異常
假設應用程式現在遇到了一個錯誤,需要拋出異常進行警示。那麼,首先要確定異常的類型。Java已經事先定義好了許多Exception,常見的有IOException/SQLException等等,更多類型可以通過查閱API來確定。當然,我們也可以繼承Exception然後建立自己的異常。接下來,建立異常執行個體,並使用throw關鍵字拋出異常。最後,在方法簽名中聲明拋出的異常類型。範例程式碼如下:
public void read(File file) throws Exception{ if(!file.exists()){ Exception e = new FileNotFoundException(); throw e; } }
四、捕獲異常
異常的捕獲、處理格式為:
public void callRead(){ try { //可能拋出異常的代碼 read(new File("filename1")); read(new File("filename2")); } catch (Exception e) { //異常處理代碼 e.printStackTrace(); } finally{ //無論如何需要執行的代碼,比如釋放資源 } }
其中,try{}catch{}是必須的,finally是可選的。可能拋出異常的代碼必須放在try{}中,否則異常無法被捕獲;當捕獲異常時,直接跳轉到catch{}進行異常處理。比如說,讀取filename1時捕獲了異常,那麼read(new File("filename2"));這局代碼將被跳過不再執行。
通常可能發生的異常不止一種,不建議都使用Exception對象進行捕獲,因為它太通用,不能反映異常的具體類型。正確的做法是對不同的異常分別處理,即疊加多個catch塊。
程式中總有一些工作比如釋放資源,無論發生異常與否都需要去做,那麼可以放在finally{}中,它在catch{}完成後一定會執行。即使前面有return語句,也將在finally{}結束後才返回。
五、再次拋出異常
Java-錯誤處理機制學習(一)異常處理