Java 異常處理引出_第1頁(yè)
Java 異常處理引出_第2頁(yè)
Java 異常處理引出_第3頁(yè)
Java 異常處理引出_第4頁(yè)
Java 異常處理引出_第5頁(yè)
已閱讀5頁(yè),還剩7頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

付費(fèi)下載

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

Java異常處理引出假設(shè)您要編寫一個(gè)Java程序,該程序讀入用戶輸入的一行文本,并在終端顯示該文本。程序如下:1importjava.io.*;2publicclassEchoInput{3publicstaticvoidmain(Stringargs[]){4System.out.println("Entertexttoecho:");5InputStreamReaderisr=newInputStreamReader(System.in);6BufferedReaderinputReader=newBufferedReader(isr);7StringinputLine=inputReader.readLine();8System.out.println("Read:"+inputLine);9}10}分析上面的代碼,在EchoInput類中,第3行聲明了main方法;第4行提示用戶輸入文本;第5、6行設(shè)置BufferedReader對(duì)像連接到InputStreamReader,而InputStreamReader又連接到標(biāo)準(zhǔn)輸入流System.in;第7行讀入一行文本;第8行用標(biāo)準(zhǔn)輸出流System.out顯示出該文本。表面看來(lái)上面的程序沒(méi)有問(wèn)題,但實(shí)際上,EchoInput類完全可能出現(xiàn)問(wèn)題。要在調(diào)用第7行的readLine方法時(shí)正確讀取輸入,這幾種假設(shè)都必須成立:假定鍵盤有效,鍵盤能與計(jì)算機(jī)正常通信;假定鍵盤數(shù)據(jù)可從操作系統(tǒng)傳輸?shù)絁ava虛擬機(jī),又從Java虛擬機(jī)傳輸inputReader。大多數(shù)情況下上述假設(shè)都成立,但不盡然。為此,Java采用異常方法,以應(yīng)對(duì)可能出現(xiàn)的錯(cuò)誤,并采取步驟進(jìn)行更正。在本例中,若試圖編譯以上代碼,將看到以下信息:Exceptioninthread"main"java.lang.Error:Unresolvedcompilationproblem:UnhandledexceptiontypeIOExceptionatEchoInput.main(EchoInput.java:7)從中可以看到,第7行調(diào)用readLine方法可能出錯(cuò):若果真如此,則產(chǎn)生IOException來(lái)記錄故障。編譯器錯(cuò)誤是在告訴您,需要更改代碼來(lái)解決這個(gè)潛在的問(wèn)題。在JDKAPI文檔中,可以看到同樣的信息。我們可以看到readLine方法,如圖1所示。

圖1.BufferedReader類的readLine方法的JDKAPI文檔

由圖1可知,readLine方法有時(shí)產(chǎn)生IOException。如何處理潛在的故障?編譯器需要“捕獲”或“聲明”IOException?!安东@(catch)”指當(dāng)readLine方法產(chǎn)生錯(cuò)誤時(shí)截獲該錯(cuò)誤,并處理和記錄該問(wèn)題。而“聲明(declare)”指錯(cuò)誤可能引發(fā)IOException,并通知調(diào)用該方法的任何代碼:可能產(chǎn)生異常。若要捕獲異常,必須添加一個(gè)特殊的“處理代碼塊”,來(lái)接收和處理IOException。于是程序改為如下:1importjava.io.*;2publicclassEchoInputHandle{3publicstaticvoidmain(Stringargs[]){4System.out.println("Entertexttoecho:");5InputStreamReaderisr=newInputStreamReader(System.in);6BufferedReaderinputReader=newBufferedReader(isr);7try{8StringinputLine=inputReader.readLine();9System.out.println("Read:"+inputLine);10}11catch(IOExceptionexc){12System.out.println(“Exceptionencountered:”+exc);13}14}15}新添的代碼塊包含關(guān)鍵字try和catch(第7,10,11,13行),表示要讀取輸入。若成功,則正常運(yùn)行。若讀取輸入時(shí)錯(cuò)誤,則捕獲問(wèn)題(由IOException對(duì)象表示),并采取相應(yīng)措施。在本例,采用的處理方式是輸出異常。若不準(zhǔn)備捕獲IOException,僅聲明異常,則要特別指定main方法可能出錯(cuò),而且特別說(shuō)明可能產(chǎn)生IOException。于是程序改為如下:1importjava.io.*;2publicclassEchoInputDeclare{3publicstaticvoidmain(Stringargs[])throwsIOException{4System.out.println("Entertexttoecho:");5InputStreamReaderisr=newInputStreamReader(System.in);6BufferedReaderinputReader=newBufferedReader(isr);7StringinputLine=inputReader.readLine();8System.out.println("Read:"+inputLine);9}10}從上面的這個(gè)簡(jiǎn)單的例子中,我們可以看出異常處理在Java代碼開發(fā)中不能被忽視。Java異常以及異常處理可將Java異常看作是一類消息,它傳送一些系統(tǒng)問(wèn)題、故障及未按規(guī)定執(zhí)行的動(dòng)作的相關(guān)信息。異常包含信息,以將信息從應(yīng)用程序的一部分發(fā)送到另一部分。編譯語(yǔ)言為何要處理異常?為何不在異常出現(xiàn)位置隨時(shí)處理具體故障?因?yàn)橛袝r(shí)候我們需要在系統(tǒng)中交流錯(cuò)誤消息,以便按照統(tǒng)一的方式處理問(wèn)題,有時(shí)是因?yàn)橛腥舾商幚韱?wèn)題的可能方式,但您不知道使用哪一種,此時(shí),可將處理異常的任務(wù)委托給調(diào)用方法的代碼。調(diào)用者通常更能了解問(wèn)題來(lái)源的上下文,能更好的確定恢復(fù)方式。圖2是一個(gè)通用消息架構(gòu)。

圖2.通用消息架構(gòu)

從上圖可以看出,必定在運(yùn)行的Java應(yīng)用程序的一些類或?qū)ο笾挟a(chǎn)生異常。出現(xiàn)故障時(shí),“發(fā)送者”將產(chǎn)生異常對(duì)象。異常可能代表Java代碼出現(xiàn)的問(wèn)題,也可能是JVM的相應(yīng)錯(cuò)誤,或基礎(chǔ)硬件或操作系統(tǒng)的錯(cuò)誤。異常本身表示消息,指發(fā)送者傳給接收者的數(shù)據(jù)“負(fù)荷”。首先,異?;陬惖念愋蛠?lái)傳輸有用信息。很多情況下,基于異常的類既能識(shí)別故障本因并能更正問(wèn)題。其次,異常還帶有可能有用的數(shù)據(jù)(如屬性)。在處理異常時(shí),消息必須有接收者;否則將無(wú)法處理產(chǎn)生異常的底層問(wèn)題。在上例中,異?!爱a(chǎn)生者”是讀取文本行的BufferedReader。在故障出現(xiàn)時(shí),將在readLine方法中構(gòu)建IOException對(duì)象。異?!敖邮照摺笔谴a本身。EchoInputHandle應(yīng)用程序的try-catch結(jié)構(gòu)中的catch塊是異常的接收者,它以字符串形式輸出異常,將問(wèn)題記錄下來(lái)。Java異常類的層次結(jié)構(gòu)在我們從總體上了解異常后,我們應(yīng)該了解如何在Java應(yīng)用程序中使用異常,即需要了解Java類的層次結(jié)構(gòu)。圖3是Java類的層次結(jié)構(gòu)圖。

圖3.Java類的層次結(jié)構(gòu)

在Java中,所有的異常都有一個(gè)共同的祖先Throwable(可拋出)。Throwable指定代碼中可用異常傳播機(jī)制通過(guò)Java應(yīng)用程序傳輸?shù)娜魏螁?wèn)題的共性。Throwable有兩個(gè)重要的子類:Exception(異常)和Error(錯(cuò)誤),二者都是Java異常處理的重要子類,各自都包含大量子類。Exception(異常)是應(yīng)用程序中可能的可預(yù)測(cè)、可恢復(fù)問(wèn)題。一般大多數(shù)異常表示中度到輕度的問(wèn)題。異常一般是在特定環(huán)境下產(chǎn)生的,通常出現(xiàn)在代碼的特定方法和操作中。在EchoInput類中,當(dāng)試圖調(diào)用readLine方法時(shí),可能出現(xiàn)IOException異常。Error(錯(cuò)誤)表示運(yùn)行應(yīng)用程序中較嚴(yán)重問(wèn)題。大多數(shù)錯(cuò)誤與代碼編寫者執(zhí)行的操作無(wú)關(guān),而表示代碼運(yùn)行時(shí)JVM(Java虛擬機(jī))出現(xiàn)的問(wèn)題。例如,當(dāng)JVM不再有繼續(xù)執(zhí)行操作所需的內(nèi)存資源時(shí),將出現(xiàn)OutOfMemoryError。Exception類有一個(gè)重要的子類RuntimeException。RuntimeException類及其子類表示“JVM常用操作”引發(fā)的錯(cuò)誤。例如,若試圖使用空值對(duì)象引用、除數(shù)為零或數(shù)組越界,則分別引發(fā)運(yùn)行時(shí)異常(NullPointerException、ArithmeticException)和ArrayIndexOutOfBoundException。Java異常的處理在Java應(yīng)用程序中,對(duì)異常的處理有兩種方式:處理異常和聲明異常。處理異常:try、catch和finally若要捕獲異常,則必須在代碼中添加異常處理器塊。這種Java結(jié)構(gòu)可能包含3個(gè)部分,都有Java關(guān)鍵字。下面的例子中使用了try-catch-finally代碼結(jié)構(gòu)。1importjava.io.*;2publicclassEchoInputTryCatchFinally{3publicstaticvoidmain(Stringargs[]){4System.out.println("Entertexttoecho:");5InputStreamReaderisr=newInputStreamReader(System.in);6BufferedReaderinputReader=newBufferedReader(isr);7try{8StringinputLine=inputReader.readLine();9System.out.println("Read:"+inputLine);10}11catch(IOExceptionexc){12System.out.println("Exceptionencountered:"+exc);13}14finally{15System.out.println("End.");16}17}18}其中:try塊:將一個(gè)或者多個(gè)語(yǔ)句放入try時(shí),則表示這些語(yǔ)句可能拋出異常。編譯器知道可能要發(fā)生異常,于是用一個(gè)特殊結(jié)構(gòu)評(píng)估塊內(nèi)所有語(yǔ)句。catch塊:當(dāng)問(wèn)題出現(xiàn)時(shí),一種選擇是定義代碼塊來(lái)處理問(wèn)題,catch塊的目的便在于此。catch塊是try塊所產(chǎn)生異常的接收者。基本原理是:一旦生成異常,則try塊的執(zhí)行中止,JVM將查找相應(yīng)的JVM。finally塊:還可以定義finally塊,無(wú)論運(yùn)行try塊代碼的結(jié)果如何,該塊里面的代碼一定運(yùn)行。在常見的所有環(huán)境中,finally塊都將運(yùn)行。無(wú)論try塊是否運(yùn)行完,無(wú)論是否產(chǎn)生異常,也無(wú)論是否在catch塊中得到處理,finally塊都將執(zhí)行。try-catch-finally規(guī)則:必須在try之后添加catch或finally塊。try塊后可同時(shí)接catch和finally塊,但至少有一個(gè)塊。必須遵循塊順序:若代碼同時(shí)使用catch和finally塊,則必須將catch塊放在try塊之后。catch塊與相應(yīng)的異常類的類型相關(guān)。一個(gè)try塊可能有多個(gè)catch塊。若如此,則執(zhí)行第一個(gè)匹配塊??汕短譼ry-catch-finally結(jié)構(gòu)。在try-catch-finally結(jié)構(gòu)中,可重新拋出異常。除了下列情況,總將執(zhí)行finally做為結(jié)束:JVM過(guò)早終止(調(diào)用System.exit(int));在finally塊中拋出一個(gè)未處理的異常;計(jì)算機(jī)斷電、失火、或遭遇病毒攻擊。聲明異常若要聲明異常,則必須將其添加到方法簽名塊的結(jié)束位置。下面是一個(gè)實(shí)例:publicvoiderrorProneMethod(intinput)throwsjava.io.IOException{//Codeforthemethod,includingoneormoremethod//callsthatmayproduceanIOException} 這樣,聲明的異常將傳給方法調(diào)用者,而且也通知了編譯器:該方法的任何調(diào)用者必須遵守處理或聲明規(guī)則。聲明異常的規(guī)則如下:必須聲明方法可拋出的任何可檢測(cè)異常(checkedexception)。非檢測(cè)性異常(uncheckedexception)不是必須的,可聲明,也可不聲明。調(diào)用方法必須遵循任何可檢測(cè)異常的處理和聲明規(guī)則。若覆蓋一個(gè)方法,則不能聲明與覆蓋方法不同的異常。聲明的任何異常必須是被覆蓋方法所聲明異常的同類或子類。Java異常處理的分類Java異常可分為可檢測(cè)異常,非檢測(cè)異常和自定義異常??蓹z測(cè)異??蓹z測(cè)異常經(jīng)編譯器驗(yàn)證,對(duì)于聲明拋出異常的任何方法,編譯器將強(qiáng)制執(zhí)行處理或聲明規(guī)則,例如:sqlExecption這個(gè)異常就是一個(gè)檢測(cè)異常。你連接JDBC時(shí),不捕捉這個(gè)異常,編譯器就通不過(guò),不允許編譯。非檢測(cè)異常非檢測(cè)異常不遵循處理或聲明規(guī)則。在產(chǎn)生此類異常時(shí),不一定非要采取任何適當(dāng)操作,編譯器不會(huì)檢查是否已解決了這樣一個(gè)異常。例如:一個(gè)數(shù)組為3個(gè)長(zhǎng)度,當(dāng)你使用下標(biāo)為3時(shí),就會(huì)產(chǎn)生數(shù)組下標(biāo)越界異常。這個(gè)異常JVM不會(huì)進(jìn)行檢測(cè),要靠程序員來(lái)判斷。有兩個(gè)主要類定義非檢測(cè)異常:RuntimeException和Error。Error子類屬于非檢測(cè)異常,因?yàn)闊o(wú)法預(yù)知它們的產(chǎn)生時(shí)間。若Java應(yīng)用程序內(nèi)存不足,則隨時(shí)可能出現(xiàn)OutOfMemoryError;起因一般不是應(yīng)用程序的特殊調(diào)用,而是JVM自身的問(wèn)題。另外,Error一般表示應(yīng)用程序無(wú)法解決的嚴(yán)重問(wèn)題。RuntimeException類也屬于非檢測(cè)異常,因?yàn)槠胀↗VM操作引發(fā)的運(yùn)行時(shí)異常隨時(shí)可能發(fā)生,此類異常一般是由特定操作引發(fā)。但這些操作在Java應(yīng)用程序中會(huì)頻繁出現(xiàn)。因此,它們不受編譯器檢查與處理或聲明規(guī)則的限制。自定義異常自定義異常是為了表示應(yīng)用程序的一些錯(cuò)誤類型,為代碼可能發(fā)生的一個(gè)或多個(gè)問(wèn)題提供新含義。可以顯示代碼多個(gè)位置之間的錯(cuò)誤的相似性,也可以區(qū)分代碼運(yùn)行時(shí)可能出現(xiàn)的相似問(wèn)題的一個(gè)或者多個(gè)錯(cuò)誤,或給出應(yīng)用程序中一組錯(cuò)誤的特定含義。例如,對(duì)隊(duì)列進(jìn)行操作時(shí),有可能出現(xiàn)兩種情況:空隊(duì)列時(shí)試圖刪除一個(gè)元素;滿隊(duì)列時(shí)試圖添加一個(gè)元素。則需要自定義兩個(gè)異常來(lái)處理這兩種情況。Java異常處理的原則和忌諱Java異常處理的原則盡可能的處理異常要盡可能的處理異常,如果條件確實(shí)不允許,無(wú)法在自己的代碼中完成處理,就考慮聲明異常。如果人為避免在代碼中處理異常,僅作聲明,則是一種錯(cuò)誤和依賴的實(shí)踐。具體問(wèn)題具體解決異常的部分優(yōu)點(diǎn)在于能為不同類型的問(wèn)題提供不同的處理操作。有效異常處理的關(guān)鍵是識(shí)別特定故障場(chǎng)景,并開發(fā)解決此場(chǎng)景的特定相應(yīng)行為。為了充分利用異常處理能力,需要為特定類型的問(wèn)題構(gòu)建特定的處理器塊。記錄可能影響應(yīng)用程序運(yùn)行的異常至少要采取一些永久的方式,記錄下可能影響應(yīng)用程序操作的異常。理想情況下,當(dāng)然是在第一時(shí)間解決引發(fā)異常的基本問(wèn)題。不過(guò),無(wú)論采用哪種處理操作,一般總應(yīng)記錄下潛在的關(guān)鍵問(wèn)題。別看這個(gè)操作很簡(jiǎn)單,但它可以幫助您用很少的時(shí)間來(lái)跟蹤應(yīng)用程序中復(fù)雜問(wèn)題的起因。根據(jù)情形將異常轉(zhuǎn)化為業(yè)務(wù)上下文若要通知一個(gè)應(yīng)用程序特有的問(wèn)題,有必要將應(yīng)用程序轉(zhuǎn)換為不同形式。若用業(yè)務(wù)特定狀態(tài)表示異常,則代碼更易維護(hù)。從某種意義上講,無(wú)論何時(shí)將異常傳到不同上下文(即另一技術(shù)層),都應(yīng)將異常轉(zhuǎn)換為對(duì)新上下文有意義的形式。Java異常處理的忌諱一般不要忽略異常在異常處理塊中,一項(xiàng)最危險(xiǎn)的舉動(dòng)是“不加通告”地處理異常。如下例所示:1try{2Class.forName("business.domain.Customer");3}4catch(ClassNotFoundExceptionexc){}經(jīng)常能夠在代碼塊中看到類似的代碼塊。有人總喜歡在編寫代碼時(shí)簡(jiǎn)單快速地編寫空處理器塊,并“自我安慰地”宣稱準(zhǔn)備在“后期”添加恢復(fù)代碼,但這個(gè)“后期”變成了“無(wú)期”。這種做法有什么壞處?如果異常對(duì)應(yīng)用程序的其他部分確實(shí)沒(méi)有任何負(fù)面影響,這未嘗不可。但事實(shí)往往并非如此,異常會(huì)擾亂應(yīng)用程序的狀態(tài)。此時(shí),這樣的代碼無(wú)異于掩耳盜鈴。這種做法若影響較輕,則應(yīng)用程序可能出現(xiàn)怪異行為。例如,應(yīng)用程序設(shè)置的一個(gè)值不見了,或GUI失效。若問(wèn)題嚴(yán)重,則應(yīng)用程序可能會(huì)出現(xiàn)重大問(wèn)題,因?yàn)楫惓N从涗浽脊收宵c(diǎn),難以處理,如重復(fù)的NullPointerExceptions。如果采取措施,記錄了捕獲的異常,則不可能遇到這個(gè)問(wèn)題。實(shí)際上,除非確認(rèn)異常對(duì)代碼其余部分絕無(wú)影響,至少也要作記錄。進(jìn)一步講,永遠(yuǎn)不要忽略問(wèn)題;否則,風(fēng)險(xiǎn)很大,在后期會(huì)引發(fā)難以預(yù)料的后果。不要使用覆蓋式異常處理塊另一個(gè)危險(xiǎn)的處理是覆蓋式處理器(blankethandler)。該代碼的基本結(jié)構(gòu)如下:1try{2//…3}4catch(Exceptione){5//…6}使用覆蓋式異常處理塊有兩個(gè)前提之一:1.代碼中只有一類問(wèn)題。這可能正確,但即便如此,也不應(yīng)使用覆蓋式異常處理,捕獲更具體的異常形式有利無(wú)弊。2.單個(gè)恢復(fù)操作始終適用。這幾乎絕對(duì)錯(cuò)誤。幾乎沒(méi)有哪個(gè)方法能放之四海而皆準(zhǔn),能應(yīng)對(duì)出現(xiàn)的任何問(wèn)題。分析下這樣編寫代碼將發(fā)生的情況。只要方法不斷拋出預(yù)期的異常集,則一切正常。但是,如果拋出了未預(yù)料到的異常,則無(wú)法看到要采取的操作。當(dāng)覆蓋式處理器對(duì)新異常類執(zhí)行千篇一律的任務(wù)時(shí),只能間接看到異常的處理結(jié)果。如果代碼沒(méi)有打印或記錄語(yǔ)句,則根本看不到結(jié)果。更糟糕的是,當(dāng)代碼發(fā)生變化時(shí),覆蓋式處理器將繼續(xù)作用于所有新異常類型,并以相同方式處理所有類型。一般不要把特定的異常轉(zhuǎn)化為更通用的異常將特定的異常轉(zhuǎn)換為更通用異常時(shí)一種錯(cuò)誤做法。一般而言,這將取消異常起初拋出時(shí)產(chǎn)生的上下文,在將異常傳到系統(tǒng)的其他位置時(shí),將更難處理。見下例:1try{2//Error-pronecode3}4catch(IOExceptione){5Stringmsg="Ifyoudidn’thaveaproblembefore,youdonow!";6thrownewException(msg);7}因?yàn)闆](méi)有原始異常的信息,所以處理器塊無(wú)法確定問(wèn)題的起因,也不知道如何更正問(wèn)題。不要處理能夠避免的異常對(duì)于有些異常類型,實(shí)際上根本不必處理。通常運(yùn)行時(shí)異常屬于此類范疇。在處理空指針或者數(shù)據(jù)索引等問(wèn)題時(shí),不必求助于異常處理。Java異常處理的應(yīng)用實(shí)例在定義銀行類時(shí),若取錢數(shù)大于余額時(shí)需要做異常處理。定義一個(gè)異常類insufficientFundsException。取錢(withdrawal)方法中可能產(chǎn)生異常,條件是余額小于取額。處理異常在調(diào)用withdrawal的時(shí)候,因此withdrawal方法要聲明拋出異常,由上一級(jí)方法調(diào)用。異常類:classInsufficientFundsExceptionextendsException{privateBankexcepbank;//銀行對(duì)象privatedoubleexcepAmount;//要取的錢InsufficientFundsException(Bankba,doubledAmount){excepbank=ba;excepAmount=dAmount;}publicStringexcepMessage(){ Stringstr="Thebalanceis"+excepbank.balance+"\n"+"Thewithdrawalwas"+excep

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論