作為一個編程新手,異常處理的概念可能很難讓你理解。並不是說概念本身很難理解,而是術語可以讓它看起來比實際更先進。而且它的功能非常強大,很容易被濫用。
在本文中,您將瞭解什麼是異常,它們為什麼重要,如何使用它們,以及要避免的常見錯誤。大多數現代語言都有某種類型的異常處理,因此如果您從Java開始,您可以隨身攜帶這些技巧中的大部分。
在Java中,異常是指在應用程序運行期間發生異常(或“異常”)的對象。拋出這樣的異常,這基本上意味著創建了一個異常對象(類似於“引發”錯誤的方式)。
這樣做的好處是,您可以捕獲拋出的異常,這樣您就可以處理異常情況,並允許應用程序繼續運行,就好像沒有什麼問題一樣。例如,C中的空指針可能會使應用程序崩潰,而Java允許拋出並捕獲
NullPointerException在空變量有可能導致崩潰之前。
請記住,異常只是一個對象,但有一個重要特徵:它必須從
Exception類或其任何子類
Exception. 雖然Java有各種各樣的內置異常,但是如果您願意,也可以創建自己的異常。一些最常見的Java異常包括:
那麼當拋出異常時會發生什麼呢?
首先,Java在immediate方法中查看是否有處理拋出的異常類型的代碼。如果處理程序不存在,它會查看調用當前方法的方法,以查看那裡是否存在句柄。如果沒有,它將查看調用該方法的方法,然後查看下一個方法,等等。如果沒有捕獲異常,應用程序將打印堆棧跟蹤,然後崩潰。(實際上,這比簡單的崩潰更為微妙,但這是一個超出本文範圍的高級主題。)
堆棧跟蹤是Java在查找異常處理程序時遍歷的所有方法的列表。堆棧跟蹤如下所示:
Exception in thread "main" java.lang.NullPointerException at com.example.myproject.Book.getTitle(Book.java:16) at com.example.myproject.Author.getBookTitles(Author.java:25) at com.example.myproject.Bootstrap.main(Bootstrap.java:14)我們可以從中收穫很多。首先,拋出的異常是
NullPointerException. 它發生在
getTitle()第16行的方法書籍.java. 該方法是從
getBookTitles()第25行作者.java. 該方法是從
main()第14行引導.java. 如您所見,瞭解所有這些使調試更容易。
但是,異常的真正好處是,您可以通過捕獲異常、糾正錯誤並在不崩潰的情況下恢復應用程序來“處理”異常情況。
假設你有
someMethod()它接受一個整數並執行一些邏輯,如果整數小於0或大於100,這些邏輯可能會中斷。這可能是拋出異常的好地方:
public void someMethod(int value) { if (value < 0 || value > 100) { throw new IllegalArgumentException為了捕捉這個異常,您需要轉到
someMethod()調用並使用try-catch塊:
public void callingMethod() { try { someMethod(200); someOtherMethod(); } catch (IllegalArgumentException e) { // handle the exception in here } // ...}try塊中的所有內容都將按順序執行,直到拋出異常為止。一旦拋出異常,將跳過所有後續語句,應用程序邏輯立即跳轉到catch塊。
在我們的示例中,我們輸入try塊並立即調用
someMethod(). 因為200不在0和100之間
IllegalArgumentException被拋出。這將立即結束執行
someMethod(),跳過try塊中的其餘邏輯(
someOtherMethod()從不調用),並在catch塊內恢復執行。
如果我們打電話會怎麼樣
someMethod(50)相反呢?這個
IllegalArgumentException不會被扔的。
someMethod()會正常執行。try塊將正常執行,調用
someOtherMethod()當someMethod()完成時。什麼時候?
someOtherMethod()結束時,將跳過catch塊
callingMethod()會繼續。
請注意,每個try塊可以有多個catch塊:
public void callingMethod() { try { someMethod(200); someOtherMethod(); } catch (IllegalArgumentException e) { // handle the exception in here } catch (NullPointerException e) { // handle the exception in here } // ...}還要注意,還存在一個可選的finally塊:
public void method() { try { // ... } catch (Exception e) { // ... } finally { // ... }}finally塊中的代碼總是被執行,不管發生什麼。如果try塊中有return語句,那麼finally塊將在返回方法之前執行。如果在catch塊中拋出另一個異常,那麼finally塊將在拋出異常之前執行。
當有對象需要在方法結束前清理時,應該使用finally塊。例如,如果您在try塊中打開了一個文件,然後拋出了一個異常,那麼finally塊允許您在離開方法之前關閉該文件。
請注意,可以使用finally塊而不使用catch塊:
public void method() { try { // ... } finally { // ... }}這允許您在允許拋出的異常向上傳播方法調用堆棧的同時執行任何必要的清理(即,您不想在此處處理異常,但仍需要首先清理)。
與大多數語言不同,Java區分了檢查異常和未檢查異常(例如,C#只有未檢查的異常)。必須在拋出異常的方法中捕獲選中的異常,否則代碼將無法編譯。
要創建選中的異常,請從
Exception. 要創建未檢查的異常,請從
RuntimeException.
任何拋出選中異常的方法都必須使用throws關鍵字在方法簽名中表示該異常。因為Java是內置的
IOException是選中的異常,以下代碼將不會編譯:
public void wontCompile() { // ... if (someCondition) { throw new IOException(); } // ...}必須首先聲明它引發選中的異常:
public void willCompile() throws IOException { // ... if (someCondition) { throw new IOException(); } // ...}請注意,方法可以聲明為引發異常,但不會實際引發異常。即便如此,仍然需要捕獲異常,否則代碼將無法編譯。
什麼時候應該使用選中或未選中的異常?
官方Java文檔中有一個關於這個問題的頁面。它用一條簡潔的經驗法則總結了這一區別:“如果可以合理地期望客戶機從異常中恢復,那麼就將其設置為檢查過的異常。如果客戶端無法執行任何操作從異常中恢復,請將其設置為未檢查的異常。“
但是這個指導方針可能已經過時了。一方面,經過檢查的異常確實會產生更健壯的代碼。另一方面,沒有其他語言像Java那樣檢查異常,這說明了兩件事:第一,這個特性對其他語言來說不夠有用,無法竊取它;第二,你完全可以不用它們。另外,選中的異常不能很好地處理Java8中引入的lambda表達式。
例外是有用的,但很容易被濫用和濫用。以下是一些提示和最佳實踐,可以幫助您避免把它們弄得一團糟。
現在您應該對異常有足夠的瞭解,瞭解它們是什麼,為什麼使用它們,以及如何將它們合併到您自己的代碼中。如果你不完全理解這個概念,那沒關係!它花了我一段時間才在我的腦子裡“咔嚓”一聲,所以你不必著急。慢慢來。
有什麼問題嗎?你知道我遺漏了其他與異常相關的提示嗎?在下面的評論中分享它們!
...誤會產生意外的結果,也可能會終止程式的執行。因此,正確地檢測和管理錯誤,才能正確地執行程式。錯誤可以有兩種型別。它們是編譯時錯誤和執行時錯誤。當有語法錯誤時,由Java編譯器指示。這些被稱為編譯時錯誤。一...
...選中的異常中,必須處理異常。如果不進行處理,程式的正確流將終止,並且不會生成類檔案。可以使用try,catch塊來處理錯誤。 圖01:檢查的異常處理 根據上述內容,FileReader從檔案中讀取資料。text1.txt檔案在指定位置不存在...
...此,可以使用final。在程式設計中,可能會有錯誤,為了正確地執行程式,處理這些錯誤是很重要的。finalize是由垃圾回收器呼叫的方法。因此,所有這些術語都有不同的含義。final是一個關鍵字,用於防止更改變數、避免方法重...
... 作為一個Java程式設計師,您應該完全理解Java虛擬機器是如何工作的,以及為什麼它允許跨平臺開發。您還應該熟悉核心Java概念,例如如何在Java中使用異常。你也可以用Java玩得很開心---用Java和處理技術創造出驚人的網路攝像...
...們將重點介紹10種最常見的程式碼氣味,尋找什麼,以及如何去除它們的氣味。如果你是一個新的程式設計師,避免這些,你的程式碼會明顯更好! ...
...這些服務提供了一個集中的目錄。在本文中,我們將學習如何實現一個伺服器來公開物件,以及如何實現一個客戶端來呼叫伺服器上的方法,以及如何在RMI登錄檔中註冊和查詢服務。 ...
... 下面的程式碼示例演示瞭如何包裝異常。方法\u 1()在其主體中丟擲一個SQLException。要使程式碼正確編譯,必須宣告丟擲異常。 ...