曰本美女∴一区二区特级A级黄色大片, 国产亚洲精品美女久久久久久2025, 页岩实心砖-高密市宏伟建材有限公司, 午夜小视频在线观看欧美日韩手机在线,国产人妻奶水一区二区,国产玉足,妺妺窝人体色WWW网站孕妇,色综合天天综合网中文伊,成人在线麻豆网观看

您好,歡迎來電子發(fā)燒友網(wǎng)! ,新用戶?[免費(fèi)注冊(cè)]

您的位置:電子發(fā)燒友網(wǎng)>源碼下載>java源碼下載>

java異常處理的設(shè)計(jì)與重構(gòu)

大小:0.5 MB 人氣: 2017-09-27 需要積分:1

  在程序設(shè)計(jì)中,進(jìn)行異常處理是非常關(guān)鍵和重要的一部分。一個(gè)程序的異常處理框架的好壞直接影響到整個(gè)項(xiàng)目的代碼質(zhì)量以及后期維護(hù)成本和難度。試想一下,如果一個(gè)項(xiàng)目從頭到尾沒有考慮過異常處理,當(dāng)程序出錯(cuò)從哪里尋找出錯(cuò)的根源?但是如果一個(gè)項(xiàng)目異常處理設(shè)計(jì)地過多,又會(huì)嚴(yán)重影響到代碼質(zhì)量以及程序的性能。因此,如何高效簡(jiǎn)潔地設(shè)計(jì)異常處理是一門藝術(shù),本文下面先講述Java異常機(jī)制最基礎(chǔ)的知識(shí),然后給出在進(jìn)行Java異常處理設(shè)計(jì)時(shí)的幾個(gè)建議。

  若有不正之處,請(qǐng)多多諒解和指正,不勝感激。

  以下是本文的目錄大綱:

  一。什么是異常

  二.Java中如何處理異常

  三。深刻理解try,catch,finally,throws,throw五個(gè)關(guān)鍵字

  四。在類繼承的時(shí)候,方法覆蓋時(shí)如何進(jìn)行異常拋出聲明

  五。異常處理和設(shè)計(jì)的幾個(gè)建議

  一。什么是異常

  異常的英文單詞是exception,字面翻譯就是“意外、例外”的意思,也就是非正常情況。事實(shí)上,異常本質(zhì)上是程序上的錯(cuò)誤,包括程序邏輯錯(cuò)誤和系統(tǒng)錯(cuò)誤。比如使用空的引用、數(shù)組下標(biāo)越界、內(nèi)存溢出錯(cuò)誤等,這些都是意外的情況,背離我們程序本身的意圖。錯(cuò)誤在我們編寫程序的過程中會(huì)經(jīng)常發(fā)生,包括編譯期間和運(yùn)行期間的錯(cuò)誤,在編譯期間出現(xiàn)的錯(cuò)誤有編譯器幫助我們一起修正,然而運(yùn)行期間的錯(cuò)誤便不是編譯器力所能及了,并且運(yùn)行期間的錯(cuò)誤往往是難以預(yù)料的。假若程序在運(yùn)行期間出現(xiàn)了錯(cuò)誤,如果置之不理,程序便會(huì)終止或直接導(dǎo)致系統(tǒng)崩潰,顯然這不是我們希望看到的結(jié)果。因此,如何對(duì)運(yùn)行期間出現(xiàn)的錯(cuò)誤進(jìn)行處理和補(bǔ)救呢?Java提供了異常機(jī)制來進(jìn)行處理,通過異常機(jī)制來處理程序運(yùn)行期間出現(xiàn)的錯(cuò)誤。通過異常機(jī)制,我們可以更好地提升程序的健壯性。

  在Java中異常被當(dāng)做對(duì)象來處理,根類是java.lang.Throwable類,在Java中定義了很多異常類(如OutOfMemoryError、NullPointerException、IndexOutOfBoundsException等),這些異常類分為兩大類:Error和Exception。

  Error是無法處理的異常,比如OutOfMemoryError,一般發(fā)生這種異常,JVM會(huì)選擇終止程序。因此我們編寫程序時(shí)不需要關(guān)心這類異常。

  Exception,也就是我們經(jīng)常見到的一些異常情況,比如NullPointerException、IndexOutOfBoundsException,這些異常是我們可以處理的異常。

  Exception類的異常包括checked exception和unchecked exception(unchecked exception也稱運(yùn)行時(shí)異常RuntimeException,當(dāng)然這里的運(yùn)行時(shí)異常并不是前面我所說的運(yùn)行期間的異常,只是Java中用運(yùn)行時(shí)異常這個(gè)術(shù)語來表示,Exception類的異常都是在運(yùn)行期間發(fā)生的)。

  unchecked exception(非檢查異常),也稱運(yùn)行時(shí)異常(RuntimeException),比如常見的NullPointerException、IndexOutOfBoundsException。對(duì)于運(yùn)行時(shí)異常,java編譯器不要求必須進(jìn)行異常捕獲處理或者拋出聲明,由程序員自行決定。

  checked exception(檢查異常),也稱非運(yùn)行時(shí)異常(運(yùn)行時(shí)異常以外的異常就是非運(yùn)行時(shí)異常),java編譯器強(qiáng)制程序員必須進(jìn)行捕獲處理,比如常見的IOExeption和SQLException。對(duì)于非運(yùn)行時(shí)異常如果不進(jìn)行捕獲或者拋出聲明處理,編譯都不會(huì)通過。

  在Java中,異常類的結(jié)構(gòu)層次圖如下圖所示:

  java異常處理的設(shè)計(jì)與重構(gòu)

  在Java中,所有異常類的父類是Throwable類,Error類是error類型異常的父類,Exception類是exception類型異常的父類,RuntimeException類是所有運(yùn)行時(shí)異常的父類,RuntimeException以外的并且繼承Exception的類是非運(yùn)行時(shí)異常。

  典型的RuntimeException包括NullPointerException、IndexOutOfBoundsException、IllegalArgumentException等。

  典型的非RuntimeException包括IOException、SQLException等。

  二.Java中如何處理異常 在Java中如果需要處理異常,必須先對(duì)異常進(jìn)行捕獲,然后再對(duì)異常情況進(jìn)行處理。如何對(duì)可能發(fā)生異常的代碼進(jìn)行異常捕獲和處理呢?使用try和catch關(guān)鍵字即可,如下面一段代碼所示:

  try { File file= new File( “d:/a.txt”); if(! file. exists()) file.createNewFile(); } catch(IOException e) { // TODO: handle exception}

  被try塊包圍的代碼說明這段代碼可能會(huì)發(fā)生異常,一旦發(fā)生異常,異常便會(huì)被catch捕獲到,然后需要在catch塊中進(jìn)行異常處理。

  這是一種處理異常的方式。在Java中還提供了另一種異常處理方式即拋出異常,顧名思義,也就是說一旦發(fā)生異常,我把這個(gè)異常拋出去,讓調(diào)用者去進(jìn)行處理,自己不進(jìn)行具體的處理,此時(shí)需要用到throw和throws關(guān)鍵字。

  下面看一個(gè)示例:

  publicclassMain { publicstaticvoidmain(String[] args) { try{ createFile(); } catch(Exception e) { // TODO: handle exception} } publicstaticvoidcreateFile() throws IOException{ File file = newFile( “d:/a.txt”); if(!file.exists()) file.createNewFile(); } }

  這段代碼和上面一段代碼的區(qū)別是,在實(shí)際的createFile方法中并沒有捕獲異常,而是用throws關(guān)鍵字聲明拋出異常,即告知這個(gè)方法的調(diào)用者此方法可能會(huì)拋出IOException。那么在main方法中調(diào)用createFile方法的時(shí)候,采用try…catch塊進(jìn)行了異常捕獲處理。

  當(dāng)然還可以采用throw關(guān)鍵字手動(dòng)來拋出異常對(duì)象。下面看一個(gè)例子:

  publicclassMain { publicstaticvoidmain(String[] args) { try{ int[] data = newint[]{ 1, 2, 3}; System. out.println(getDataByIndex(- 1,data)); } catch(Exception e) { System.out.println(e.getMessage()); } } publicstaticintgetDataByIndex( intindex, int[] data) {if(index《 0||index》=data.length) thrownewArrayIndexOutOfBoundsException( “數(shù)組下標(biāo)越界”); returndata[index]; } }

  然后在catch塊中進(jìn)行捕獲。

  也就說在Java中進(jìn)行異常處理的話,對(duì)于可能會(huì)發(fā)生異常的代碼,可以選擇三種方法來進(jìn)行異常處理:

  1)對(duì)代碼塊用try..catch進(jìn)行異常捕獲處理;

  2)在 該代碼的方法體外用throws進(jìn)行拋出聲明,告知此方法的調(diào)用者這段代碼可能會(huì)出現(xiàn)這些異常,你需要謹(jǐn)慎處理。此時(shí)有兩種情況:

  如果聲明拋出的異常是非運(yùn)行時(shí)異常,此方法的調(diào)用者必須顯示地用try..catch塊進(jìn)行捕獲或者繼續(xù)向上層拋出異常。

  如果聲明拋出的異常是運(yùn)行時(shí)異常,此方法的調(diào)用者可以選擇地進(jìn)行異常捕獲處理。

  3)在代碼塊用throw手動(dòng)拋出一個(gè)異常對(duì)象,此時(shí)也有兩種情況,跟2)中的類似:

  如果拋出的異常對(duì)象是非運(yùn)行時(shí)異常,此方法的調(diào)用者必須顯示地用try..catch塊進(jìn)行捕獲或者繼續(xù)向上層拋出異常。

  如果拋出的異常對(duì)象是運(yùn)行時(shí)異常,此方法的調(diào)用者可以選擇地進(jìn)行異常捕獲處理。

 ?。ㄈ绻罱K將異常拋給main方法,則相當(dāng)于交給jvm自動(dòng)處理,此時(shí)jvm會(huì)簡(jiǎn)單地打印異常信息

  三。深刻理解try,catch,finally,throws,throw五個(gè)關(guān)鍵字    下面我們來看一下異常機(jī)制中五個(gè)關(guān)鍵字的用法以及需要注意的地方。

  1.try,catch,finally

  try關(guān)鍵字用來包圍可能會(huì)出現(xiàn)異常的邏輯代碼,它單獨(dú)無法使用,必須配合catch或者finally使用。Java編譯器允許的組合使用形式只有以下三種形式:

  try…catch…; try….finally……; try….catch…finally…

  當(dāng)然catch塊可以有多個(gè),注意try塊只能有一個(gè),finally塊是可選的(但是最多只能有一個(gè)finally塊)。

  三個(gè)塊執(zhí)行的順序?yàn)閠ry—》catch—》finally。

  當(dāng)然如果沒有發(fā)生異常,則catch塊不會(huì)執(zhí)行。但是finally塊無論在什么情況下都是會(huì)執(zhí)行的(這點(diǎn)要非常注意,因此部分情況下,都會(huì)將釋放資源的操作放在finally塊中進(jìn)行)。

  在有多個(gè)catch塊的時(shí)候,是按照catch塊的先后順序進(jìn)行匹配的,一旦異常類型被一個(gè)catch塊匹配,則不會(huì)與后面的catch塊進(jìn)行匹配。

  在使用try..catch..finally塊的時(shí)候,注意千萬不要在finally塊中使用return,因?yàn)閒inally中的return會(huì)覆蓋已有的返回值。下面看一個(gè)例子:

  import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; publicclassMain { publicstaticvoidmain(String[] args) { String str =newMain().openFile(); System. out.println(str); } publicString openFile() { try{ FileInputStream inputStream = newFileInputStream( “d:/a.txt”); intch = inputStream.read(); System. out.println( “aaa”); return“step1”; } catch(FileNotFoundException e) { System.out.println( “file not found”); return“step2”; } catch(IOException e) { System. out.println( “io exception”); return“step3”; } finally{ System. out.println( “finally block”); //return “finally”;} } }

  這段程序的輸出結(jié)果為:

  java異常處理的設(shè)計(jì)與重構(gòu)

  可以看出,在try塊中發(fā)生FileNotFoundException之后,就跳到第一個(gè)catch塊,打印”file not found”信息,并將”step2”賦值給返回值,然后執(zhí)行finally塊,最后將返回值返回。

  從這個(gè)例子說明,無論try塊或者catch塊中是否包含return語句,都會(huì)執(zhí)行finally塊。

  如果將這個(gè)程序稍微修改一下,將finally塊中的return語句注釋去掉,運(yùn)行結(jié)果是:

  java異常處理的設(shè)計(jì)與重構(gòu)

  最后打印出的是”finally”,返回值被重新覆蓋了。

  因此如果方法有返回值,切忌不要再finally中使用return,這樣會(huì)使得程序結(jié)構(gòu)變得混亂。

  2.throws和thow關(guān)鍵字

  1)throws出現(xiàn)在方法的聲明中,表示該方法可能會(huì)拋出的異常,然后交給上層調(diào)用它的方法程序處理,允許throws后面跟著多個(gè)異常類型;

  2)一般會(huì)用于程序出現(xiàn)某種邏輯時(shí)程序員主動(dòng)拋出某種特定類型的異常。throw只會(huì)出現(xiàn)在方法體中,當(dāng)方法在執(zhí)行過程中遇到異常情況時(shí),將異常信息封裝為異常對(duì)象,然后throw出去。throw關(guān)鍵字的一個(gè)非常重要的作用就是 異常類型的轉(zhuǎn)換(會(huì)在后面闡述道)。

  throws表示出現(xiàn)異常的一種可能性,并不一定會(huì)發(fā)生這些異常;throw則是拋出了異常,執(zhí)行throw則一定拋出了某種異常對(duì)象。兩者都是消極處理異常的方式(這里的消極并不是說這種方式不好),只是拋出或者可能拋出異常,但是不會(huì)由方法去處理異常,真正的處理異常由此方法的上層調(diào)用處理。

  四。在類繼承的時(shí)候,方法覆蓋時(shí)如何進(jìn)行異常拋出聲明

  本小節(jié)討論子類重寫父類方法的時(shí)候,如何確定異常拋出聲明的類型。下面是三點(diǎn)原則:

  1)父類的方法沒有聲明異常,子類在重寫該方法的時(shí)候不能聲明異常;

  2)如果父類的方法聲明一個(gè)異常exception1,則子類在重寫該方法的時(shí)候聲明的異常不能是exception1的父類;

  3)如果父類的方法聲明的異常類型只有非運(yùn)行時(shí)異常(運(yùn)行時(shí)異常),則子類在重寫該方法的時(shí)候聲明的異常也只能有非運(yùn)行時(shí)異常(運(yùn)行時(shí)異常),不能含有運(yùn)行時(shí)異常(非運(yùn)行時(shí)異常)。

  java異常處理的設(shè)計(jì)與重構(gòu)

  五。異常處理和設(shè)計(jì)的幾個(gè)建議 以下是根據(jù)前人總結(jié)的一些異常處理的建議:

  1.只在必要使用異常的地方才使用異常,不要用異常去控制程序的流程

  謹(jǐn)慎地使用異常,異常捕獲的代價(jià)非常高昂,異常使用過多會(huì)嚴(yán)重影響程序的性能。如果在程序中能夠用if語句和Boolean變量來進(jìn)行邏輯判斷,那么盡量減少異常的使用,從而避免不必要的異常捕獲和處理。比如下面這段經(jīng)典的程序:

  publicvoiduseExceptionsForFlowControl() { try{ while( true) { increaseCount(); } }catch(MaximumCountReachedException ex) { } //Continue execution }publicvoidincreaseCount() throwsMaximumCountReachedException { if(count 》= 5000)thrownewMaximumCountReachedException(); }

  上邊的useExceptionsForFlowControl()用一個(gè)無限循環(huán)來增加count直到拋出異常,這種做法并沒有說讓代碼不易讀,而是使得程序執(zhí)行效率降低。

  2.切忌使用空catch塊

  在捕獲了異常之后什么都不做,相當(dāng)于忽略了這個(gè)異常。千萬不要使用空的catch塊,空的catch塊意味著你在程序中隱藏了錯(cuò)誤和異常,并且很可能導(dǎo)致程序出現(xiàn)不可控的執(zhí)行結(jié)果。如果你非??隙ú东@到的異常不會(huì)以任何方式對(duì)程序造成影響,最好用Log日志將該異常進(jìn)行記錄,以便日后方便更新和維護(hù)。

  3.檢查異常和非檢查異常的選擇

  一旦你決定拋出異常,你就要決定拋出什么異常。這里面的主要問題就是拋出檢查異常還是非檢查異常。

  檢查異常導(dǎo)致了太多的try…catch代碼,可能有很多檢查異常對(duì)開發(fā)人員來說是無法合理地進(jìn)行處理的,比如SQLException,而開發(fā)人員卻不得不去進(jìn)行try…catch,這樣就會(huì)導(dǎo)致經(jīng)常出現(xiàn)這樣一種情況:邏輯代碼只有很少的幾行,而進(jìn)行異常捕獲和處理的代碼卻有很多行。這樣不僅導(dǎo)致邏輯代碼閱讀起來晦澀難懂,而且降低了程序的性能。

  我個(gè)人建議盡量避免檢查異常的使用,如果確實(shí)該異常情況的出現(xiàn)很普遍,需要提醒調(diào)用者注意處理的話,就使用檢查異常;否則使用非檢查異常。

  因此,在一般情況下,我覺得盡量將檢查異常轉(zhuǎn)變?yōu)榉菣z查異常交給上層處理。

  4.注意catch塊的順序

  不要把上層類的異常放在最前面的catch塊。比如下面這段代碼:

  try{ FileInputStream inputStream = newFileInputStream( “d:/a.txt”); intch = inputStream.read(); System. out.println( “aaa”); return“step1”; } catch(IOException e) {    System. out.println( “io exception”);   return“step2”; }catch(FileNotFoundException e) { System. out.println( “file not found”);    return“step3”; } finally{ System. out.println( “finally block”); //return “finally”;}

  第二個(gè)catch的FileNotFoundException將永遠(yuǎn)不會(huì)被捕獲到,因?yàn)镕ileNotFoundException是IOException的子類。

  5.不要將提供給用戶看的信息放在異常信息里

  比如下面這段代碼:

  /** * Java學(xué)習(xí)交流QQ群:589809992 我們一起學(xué)Java! */publicclassMain{publicstaticvoidmain(String[] args) { try{ String user = null; String pwd =null; login(user,pwd); } catch(Exception e) { System.out.println(e.getMessage()); } }publicstaticvoidlogin(String user,String pwd) { if(user== null||pwd== null)thrownewNullPointerException( “用戶名或者密碼為空”); //。。.} }

  展示給用戶錯(cuò)誤提示信息最好不要跟程序混淆一起,比較好的方式是將所有錯(cuò)誤提示信息放在一個(gè)配置文件中統(tǒng)一管理。

  6.避免多次在日志信息中記錄同一個(gè)異常

  只在異常最開始發(fā)生的地方進(jìn)行日志信息記錄。很多情況下異常都是層層向上跑出的,如果在每次向上拋出的時(shí)候,都Log到日志系統(tǒng)中,則會(huì)導(dǎo)致無從查找異常發(fā)生的根源。

  7.異常處理盡量放在高層進(jìn)行

  盡量將異常統(tǒng)一拋給上層調(diào)用者,由上層調(diào)用者統(tǒng)一之時(shí)如何進(jìn)行處理。如果在每個(gè)出現(xiàn)異常的地方都直接進(jìn)行處理,會(huì)導(dǎo)致程序異常處理流程混亂,不利于后期維護(hù)和異常錯(cuò)誤排查。由上層統(tǒng)一進(jìn)行處理會(huì)使得整個(gè)程序的流程清晰易懂。

  8.在finally中釋放資源

  如果有使用文件讀取、網(wǎng)絡(luò)操作以及數(shù)據(jù)庫(kù)操作等,記得在finally中釋放資源。這樣不僅會(huì)使得程序占用更少的資源,也會(huì)避免不必要的由于資源未釋放而發(fā)生的異常情況。

非常好我支持^.^

(0) 0%

不好我反對(duì)

(0) 0%

      發(fā)表評(píng)論

      用戶評(píng)論
      評(píng)價(jià):好評(píng)中評(píng)差評(píng)

      發(fā)表評(píng)論,獲取積分! 請(qǐng)遵守相關(guān)規(guī)定!

      ?