Java有用處置異常的三個准繩。本站提示廣大學習愛好者:(Java有用處置異常的三個准繩)文章只能為提供參考,不一定能成為您想要的結果。以下是Java有用處置異常的三個准繩正文
異常之所所以一種壯大的調試手腕,在於其答復了以下三個成績:
1、甚麼出了錯?
2、在哪出的錯?
3、為何失足?
在有用應用異常的情形下,異常類型答復了“甚麼”被拋出,異常客棧跟蹤答復了“在哪“拋出,異常信息答復了“為何“會拋出,假如你的異常沒有答復以上全體成績,那末能夠你沒有很好地應用它們。
有三個准繩可以贊助你在調試進程中最年夜限制地應用好異常,這三個准繩是:
1、詳細明白
2、延遲拋出
3、延遲捕捉
為了論述有用異常處置的這三個准繩,本文經由過程誣捏小我財政治理器類JCheckbook停止評論辯論,JCheckbook用於記載及追蹤諸如存取款,單子開具之類的銀行賬戶運動。
詳細明白
Java界說了一個異常類的條理構造,其以Throwable開端,擴大出Error和Exception,而Exception又擴大出RuntimeException.如圖1所示.
這四個類是泛化的,其實不供給若干失足信息,固然實例化這幾個類是語法上正當的(如:new Throwable()),然則最好照樣把它們當虛基類看,應用它們加倍特化的子類。Java曾經供給了年夜量異常子類,如需加倍詳細,你也能夠界說本身的異常類。
例 如:java.io package包中界說了Exception類的子類IOException,加倍特化確的是 FileNotFoundException,EOFException和ObjectStreamException這些IOException的子 類。每種都描寫了一類特定的I/O毛病:分離是文件喪失,異常文件開頭和毛病的序列化對象流.異常越詳細,我們的法式就可以更好地答復”甚麼出了錯”這個 成績。
捕 獲異常時盡可能明白也很主要。例如:JCheckbook可以經由過程從新訊問用戶文件名來處置FileNotFoundException,關於 EOFException,它可以依據異常拋出前讀取的信息持續運轉。假如拋出的是ObjectStreamException,則法式應當提醒用戶文件 已破壞,應該應用備份文件或許其他文件。
Java讓明白捕捉異常變得輕易,由於我們可以對統一try塊界說多個catch塊,從而對每種異常分離停止適當的處置。
File prefsFile = new File(prefsFilename); try{ readPreferences(prefsFile); } catch (FileNotFoundException e){ // alert the user that the specified file // does not exist } catch (EOFException e){ // alert the user that the end of the file // was reached } catch (ObjectStreamException e){ // alert the user that the file is corrupted } catch (IOException e){ // alert the user that some other I/O // error occurred }
JCheckbook 經由過程應用多個catch塊來給用戶供給捕捉到異常的明白信息。舉例來講:假如捕捉了FileNotFoundException,它可以提醒用戶指定另外一 個文件,某些情形下多個catch塊帶來的額定編碼任務量能夠長短需要的累贅,但在這個例子中,額定的代碼切實其實贊助法式供給了對用戶更友愛的呼應。
除前三個catch塊處置的異常以外,最初一個catch塊在IOException拋出時給用戶供給了更泛化的毛病信息.如許一來,法式便可以盡量供給詳細的信息,但也有才能處置未預感到的其他異常。
有 時開辟人員會捕捉范化異常,並顯示異常類稱號或許打印客棧信息以求"詳細"。萬萬別這麼干!用戶看到java.io.EOFException
或許客棧信息 只會頭疼而不是取得贊助。應該捕捉詳細的異常而且用"人話"給用戶提醒確實的信息。不外,異常客棧卻是可以在你的日記文件裡打印。記住,異常和客棧信息是用來贊助開辟人 員而不是用戶的。
最初,應當留意到JCheckbook並沒有在readPreferences()
中捕捉異常,而是將捕捉和處置異常留到用戶界面層來做,如許就可以用對話框或其他方法來告訴用戶。這被稱為"延遲捕捉",下文就談判到。
延遲拋出
異常客棧信息供給了招致異常湧現的辦法挪用鏈的准確次序,包含每一個辦法挪用的類名,辦法名,代碼文件名乃至行數,以此來准確定位異常湧現的現場。
java.lang.NullPointerException at java.io.FileInputStream.open(Native Method) at java.io.FileInputStream.<init>(FileInputStream.java:103) at jcheckbook.JCheckbook.readPreferences(JCheckbook.java:225) at jcheckbook.JCheckbook.startup(JCheckbook.java:116) at jcheckbook.JCheckbook.<init>(JCheckbook.java:27) at jcheckbook.JCheckbook.main(JCheckbook.java:318)
以 上展現了FileInputStream類的open()辦法拋出NullPointerException的情形。不外留意 FileInputStream.close()
是尺度Java類庫的一部門,極可能招致這個異常的成績緣由在於我們的代碼自己而不是Java API。所以成績極可能湧現在後面的個中一個辦法,幸虧它也在客棧信息中打印出來了。
不幸的是,NullPointerException是Java中信息量起碼的(卻也是最常遭受且讓人瓦解的)異常。它壓根不提我們最關懷的工作:究竟哪裡是null。所以我們不能不回退幾步去找哪裡出了錯。
經由過程慢慢回退跟蹤客棧信息並檢討代碼,我們可以肯定毛病緣由是向readPreferences()
傳入了一個空文件名參數。既然readPreferences()
曉得它不克不及處置空文件名,所以立時檢討該前提:
public void readPreferences(String filename) throws IllegalArgumentException{ if (filename == null){ throw new IllegalArgumentException("filename is null"); } //if //...perform other operations... InputStream in = new FileInputStream(filename); //...read the preferences file... }
經由過程延遲拋出異常(又稱"敏捷掉敗"),異常得以清楚又精確。客棧信息立刻反應出甚麼出了錯(供給了不法參數值),為何失足(文件名不克不及為空值),和哪裡出的錯(readPreferences()
的前部門)。如許我們的客棧信息就可以照實供給:
java.lang.IllegalArgumentException: filename is null at jcheckbook.JCheckbook.readPreferences(JCheckbook.java:207) at jcheckbook.JCheckbook.startup(JCheckbook.java:116) at jcheckbook.JCheckbook.<init>(JCheckbook.java:27) at jcheckbook.JCheckbook.main(JCheckbook.java:318)
別的,個中包括的異常信息("文件名為空")經由過程明白答復甚麼為空這一成績使得異常供給的信息加倍豐碩,而這一謎底是我們之前代碼中拋出的NullPointerException所沒法供給的。
經由過程在檢測到毛病時連忙拋出異常來完成敏捷掉敗,可以有用防止不用要的對象結構或資本占用,好比文件或收集銜接。異樣,翻開這些資本所帶來的清算操作也能夠省卻。
延遲捕捉
菜鳥和高手都能夠犯的一個錯是,在法式有才能處置異常之前就捕捉它。Java編譯器經由過程請求檢討出的異常必需被捕捉或拋出而直接滋長了這類行動。天然而然的做法就是立刻將代碼用try塊包裝起來,並應用catch捕捉異常,以避免編譯器報錯。
問 題在於,捕捉以後該拿異常怎樣辦?最不應做的就是甚麼都不做。空的catch塊等於把全部異常丟進黑洞,可以或許解釋什麼時候何處為什麼失足的一切信息都邑永久喪失。把異常寫到日記中還略微好點,至多還有記載可查。但我們總不克不及期望用戶去浏覽或許懂得日記文件和異常信息。讓readPreferences()
顯示毛病信息對話框也不適合,由於固然JCheckbook今朝是桌面運用法式,但我們還籌劃將它釀成基於HTML的Web運用。那樣的話,顯示毛病對話框明顯不是個選擇。同時,不論HTML照樣C/S版本,設置裝備擺設信息都是在辦事器上讀取的,而毛病信息須要顯示給Web閱讀器或許客戶端法式。 readPreferences()
應該在設計時將這些將來需求也斟酌在內。恰當分別用戶界面代碼和法式邏輯可以進步我們代碼的可重用性。
在有前提處置異常之前過早捕捉它,平日會招致更嚴重的毛病和其他異常。例如,假如上文的readPreferences()
辦法在挪用FileInputStream結構辦法時立刻捕捉和記載能夠拋出的FileNotFoundException,代碼會釀成上面如許:
public void readPreferences(String filename){ //... InputStream in = null; // DO NOT DO THIS!!! try{ in = new FileInputStream(filename); } catch (FileNotFoundException e){ logger.log(e); } in.read(...); //... }
下面的代碼在完整沒有才能從FileNotFoundException中恢復過去的情形下就捕捉了它。假如文件沒法找到,上面的辦法明顯沒法讀取它。假如 readPreferences()被請求讀取不存在的文件時會產生甚麼情形?固然,FileNotFoundException會被記載上去,假如我們 其時去看日記文件的話,就會曉得。但是當法式測驗考試從文件中讀取數據時會產生甚麼?既然文件不存在,變量in就是空的,一個 NullPointerException就會被拋出。
調試法式時,天性告知我們要看日記最初面的信息。那將會是NullPointerException,異常讓人憎惡的是這個異常異常不詳細。毛病信息不只誤導我們甚麼出了錯(真實的毛病是FileNotFoundException而不是NullPointerException),還誤導了毛病的出處。真正 的成績出在拋出NullPointerException處的數行以外,這之間有能夠存在好幾回辦法的挪用和類的燒毀。我們的留意力被這條小魚從真實的毛病處吸引了過去,一向到我們往回看日記能力發明成績的泉源。
既然readPreferences()
真正應當做的工作不是捕捉這些異常,那應當是甚麼?看起來有點有悖常理,平日最適合的做法實際上是甚麼都不做,不要立時捕捉異常。把義務交給 readPreferences()
的挪用者,讓它來研討處置設置裝備擺設文件缺掉的適當辦法,它有能夠會提醒用戶指定其他文件,或許應用默許值,其實不可的話也 許正告用戶並加入法式。
把異常處置的義務往挪用鏈的下游傳遞的方法,就是在辦法的throws子句聲明異常。在聲明能夠拋出的異常時,留意越詳細越好。這用於標識出挪用你辦法的法式須要知曉而且預備處置的異常類型。例如,“延遲捕捉”版本的readPreferences()
能夠是如許的:
public void readPreferences(String filename) throws IllegalArgumentException, FileNotFoundException, IOException{ if (filename == null){ throw new IllegalArgumentException("filename is null"); } //if //... InputStream in = new FileInputStream(filename); //... }
技 術下去說,我們獨一須要聲明的異常是IOException,但我們明白聲清楚明了辦法能夠拋出FileNotFoundException。 IllegalArgumentException不是必需聲明的,由於它長短檢討性異常(即RuntimeException的子類)。但是聲明它是為 了文檔化我們的代碼(這些異常也應當在辦法的JavaDocs中標注出來)。
當 然,終究你的法式須要捕捉異常,不然會心外終止。但這裡的技能是在適合的層面捕捉異常,以便你的法式要末可以從異常中成心義地恢復並持續下去,而不招致更 深刻的毛病;要末可以或許為用戶供給明白的信息,包含引誘他們從毛病中恢復過去。假如你的辦法沒法勝任,那末就不要處置異常,把它留到前面捕捉和在適當的層面處置。
總結
經歷豐碩的開辟人員都曉得,調試法式的最年夜難點不在於修復缺點,而在於從海量的代碼中找有缺陷的藏身的地方。只需遵守本文的三個准繩,就可以讓你的異常協助你跟蹤和祛除缺點,使你的法式加倍硬朗,對用戶加倍友愛。以上就是這篇文章的全體內容,願望能對年夜家的進修或許任務帶來必定的贊助。