如何拋出異常
在捕獲異常之前,某些代碼必須拋出一個,任何代碼都可能拋出異常:你的代碼,來自其他人編寫的包中的代碼,例如Java平臺附帶的包或Java運行時環境,無論拋出什么異常,它總是使用throw語句拋出。
你可能已經注意到,Java平臺提供了許多異常類,所有類都是Throwable類的后代,并且所有類都允許程序區分在程序執行期間可能發生的各種類型的異常。
你還可以創建自己的異常類來表示你編寫的類中可能出現的問題,實際上,如果你是程序包開發人員,則可能必須創建自己的一組異常類,以允許用戶將程序包中可能發生的錯誤與Java平臺或其他程序包中發生的錯誤區分開來。
你還可以創建鏈式異常,有關更多信息,請參閱“鏈式異常”部分。
throw語句所有方法都使用throw語句拋出異常,throw語句需要一個參數:一個throwable對象,Throwable對象是Throwable類的任何子類的實例,這是一個throw語句的例子。
throw someThrowableObject;
讓我們看一下上下文中的throw語句,以下pop方法取自實現公共堆棧對象的類,該方法從堆棧中刪除頂部元素并返回該對象。
public Object pop() { Object obj; if (size == 0) { throw new EmptyStackException(); } obj = objectAt(size - 1); setObjectAt(size - 1, null); size--; return obj; }
pop方法檢查堆棧上是否有任何元素,如果堆棧為空(其大小等于0),則pop實例化一個新的EmptyStackException對象(java.util的成員)并拋出它,本章中的創建異常類部分介紹了如何創建自己的異常類,現在,你需要記住的是,你只能拋出從java.lang.Throwable類繼承的對象。
請注意,pop方法的聲明不包含throws子句,EmptyStackException不是已檢查的異常,因此不需要pop來聲明它可能發生。
Throwable類及其子類從Throwable類繼承的對象包括直接后代(直接從Throwable類繼承的對象)和間接后代(從Throwable類的子級或孫級繼承的對象),下圖說明了Throwable類的類層次結構及其最重要的子類,如你所見,Throwable有兩個直接后代:Error和Exception。
Error類當發生Java虛擬機中的動態鏈接故障或其他硬故障時,虛擬機拋出Error,簡單程序通常不會捕獲或拋出Errors。
Exception類大多數程序拋出并捕獲從Exception類派生的對象,Exception表示發生了問題,但這不是一個嚴重的系統問題,你編寫的大多數程序將拋出并捕獲Exception而不是Error。
Java平臺定義了Exception類的許多后代,這些后代表示可能發生的各種類型的異常。例如,IllegalAccessException表示無法找到特定方法,NegativeArraySizeException表示程序試圖創建負大小的數組。
一個Exception子類RuntimeException保留用于指示錯誤使用API??的異常,運行時異常的一個示例是NullPointerException,當方法嘗試通過空引用訪問對象的成員時發生,未經檢查的異常 — 爭議部分討論了為什么大多數應用程序不應拋出運行時異?;?b>RuntimeException子類。
鏈式異常應用程序通常會通過拋出另一個異常來響應異常,實際上,第一個異常導致第二個異常,了解一個異常何時導致另一個異常非常有用,鏈式異常有助于程序員執行此操作。
以下是Throwable中支持鏈式異常的方法和構造函數。
Throwable getCause() Throwable initCause(Throwable) Throwable(String, Throwable) Throwable(Throwable)
initCause和Throwable構造函數的Throwable參數是導致當前異常的異常,getCause返回導致當前異常的異常,initCause設置當前異常的原因。
以下示例顯示如何使用鏈式異常。
try { } catch (IOException e) { throw new SampleException("Other IOException", e); }
在此示例中,捕獲IOException時,會創建一個新的SampleException異常,并附加原始原因,并將異常鏈拋出到下一個更高級別的異常處理程序。
訪問堆棧跟蹤信息現在讓我們假設更高級別的異常處理程序想要以自己的格式轉儲堆棧跟蹤。
定義:堆棧跟蹤提供有關當前線程的執行歷史記錄的信息,并列出在發生異常時調用的類和方法的名稱,堆棧跟蹤是一種有用的調試工具,通常在拋出異常時可以利用它。
以下代碼顯示如何在異常對象上調用getStackTrace方法。
catch (Exception cause) { StackTraceElement elements[] = cause.getStackTrace(); for (int i = 0, n = elements.length; i < n; i++) { System.err.println(elements[i].getFileName() + ":" + elements[i].getLineNumber() + ">> " + elements[i].getMethodName() + "()"); } }Logging API
下一個代碼段記錄catch塊中發生異常的位置,但是,它不是手動解析堆棧跟蹤并將輸出發送到System.err(),而是使用java.util.logging包中的日志記錄工具將輸出發送到文件。
try { Handler handler = new FileHandler("OutFile.log"); Logger.getLogger("").addHandler(handler); } catch (IOException e) { Logger logger = Logger.getLogger("package.name"); StackTraceElement elements[] = e.getStackTrace(); for (int i = 0, n = elements.length; i < n; i++) { logger.log(Level.WARNING, elements[i].getMethodName()); } }創建異常類
當面對選擇要拋出的異常類型時,你可以使用其他人編寫的異常 — Java平臺提供了許多可以使用的異常類 — 或者你可以編寫自己的異常類,如果你對以下任何問題的回答是肯定的,你應該編寫自己的異常類;否則,你可能會使用別人的。
你是否需要Java平臺中未表示的異常類型?
如果他們可以將你的異常與其他供應商編寫的類別所引發的異常區分開來,它會幫助用戶嗎?
你的代碼是否會拋出多個相關的異常?
如果你使用其他人的異常,用戶是否可以訪問這些異常?一個類似的問題是,你的包是否應該獨立且自包含?
一個例子假設你正在編寫鏈表類,該類支持以下方法,其中包括:
objectAt(int n) — 返回列表中第n個位置的對象,如果參數小于0或大于列表中當前對象的數量,則引發異常。
firstObject() — 返回列表中的第一個對象,如果列表不包含任何對象,則拋出異常。
indexOf(Object o) — 在列表中搜索指定的Object并返回其在列表中的位置,如果傳遞給方法的對象不在列表中,則拋出異常。
鏈表類可以拋出多個異常,并且能夠通過一個異常處理程序捕獲鏈表所引發的所有異常會很方便,此外,如果你計劃在包中分發鏈表,則應將所有相關代碼打包在一起,因此,鏈表應該提供自己的一組異常類。
下圖說明了鏈表拋出的異常的一個可能的類層次結構。
選擇超類任何Exception子類都可以用作LinkedListException的父類,但是,快速瀏覽這些子類就會發現它們不合適,因為它們太專業化或與LinkedListException完全無關,因此,LinkedListException的父類應該是Exception。
你編寫的大多數applet和應用程序都會拋出Exception對象,Error通常用于系統中嚴重的硬錯誤,例如阻止JVM運行的錯誤。
對于可讀代碼,最好將字符串Exception附加到從Exception類繼承(直接或間接)的所有類的名稱。上一篇:捕獲和處理異常
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/77477.html
捕獲和處理異常 本節描述如何使用三個異常處理程序組件 — try、catch和finally塊 — 來編寫異常處理程序,然后,解釋了Java SE 7中引入的try-with-resources語句,try-with-resources語句特別適用于使用Closeable資源的情況,例如流。 本節的最后一部分將介紹一個示例,并分析各種場景中發生的情況。 以下示例定義并實現名為ListOfNumbe...
異常的優點 現在你已經知道了什么是異常以及如何使用它們,現在是時候了解在程序中使用異常的優勢了。 優點1:將錯誤處理代碼與常規代碼分開 異常提供了從程序的主邏輯中分離異常發生時應該做什么的細節的方法,在傳統的編程中,錯誤檢測、報告和處理通常會導致混亂的意大利面代碼,例如,考慮這里的偽代碼方法將整個文件讀入內存。 readFile { open the file; determine...
捕獲或指定要求 有效的Java編程語言代碼必須遵守捕獲或指定需求,這意味著可能拋出某些異常的代碼必須包含以下任一項: 捕獲異常的try語句,try必須為異常提供處理程序,如捕獲和處理異常中所述。 一種方法,指定它可以拋出異常,該方法必須提供一個throws子句,列出異常,如通過方法拋出指定異常中所述。 不符合捕獲或指定要求的代碼將無法編譯。 并非所有異常都受捕獲或指定要求的約束,為了理解原因,...
摘要:挺多人咨詢的,異常處理用切面注解去實現去全局異常處理。全局異常處理類,代碼如下代碼解析如下抽象類是用來處理全局錯誤時進行擴展和實現注解標記的切面排序,值越小擁有越高的優先級,這里設置優先級偏高。 本文內容 為什么要全局異常處理? WebFlux REST 全局異常處理實戰 小結 摘錄:只有不斷培養好習慣,同時不斷打破壞習慣,我們的行為舉止才能夠自始至終都是正確的。 一、為什么要全局...
摘要:無需檢查的異常也是的子類。從低層拋出的需檢查異常強制要求調用方捕獲或是拋出該異常。當前執行的線程將會停止并報告該異常。單元測試允許我在使用中查看異常,并且作為一個可以被執行的文檔來使用。不要捕獲最高層異常繼承的異常同樣是的子類。 前言 異常處理的問題之一是知道何時以及如何去使用它。我會討論一些異常處理的最佳實踐,也會總結最近在異常處理上的一些爭論。 作為程序員,我們想要寫高質量的能夠解...
閱讀 2066·2021-09-22 15:54
閱讀 1830·2021-09-04 16:40
閱讀 854·2019-08-30 15:56
閱讀 2623·2019-08-30 15:44
閱讀 2150·2019-08-30 13:52
閱讀 1120·2019-08-29 16:35
閱讀 3340·2019-08-29 16:31
閱讀 2562·2019-08-29 13:48