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