第8章異常與斷言_第1頁
第8章異常與斷言_第2頁
第8章異常與斷言_第3頁
第8章異常與斷言_第4頁
第8章異常與斷言_第5頁
已閱讀5頁,還剩39頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

1、2022-5-5With JavaBlueJObject firstPLP封面封面清華大學(xué)出版社第8章異常與斷言8.1 Throwable家族 2518.1.1 異常的概念8.1.2 Error和Exception8.1.3 拋出異常8.1.4自定義異常類8.2 捕獲和處理2598.2.1 try和catch子句8.2.2 finally子句8.3 斷言2648.3.1 斷言的語義和語法8.3.2 斷言的使用指南錯(cuò)誤是真理的鄰居,因此它欺騙了我們。泰戈?duì)柫魑灱?章引言章引言一個(gè)定義良好的API,包含了使用該方法的前置條件和后置條件。然而,程序運(yùn)行的環(huán)境是復(fù)雜的,程序在執(zhí)行過程中可能遇到各種錯(cuò)誤

2、。為此,源代碼要為可能遇到錯(cuò)誤做一些準(zhǔn)備。Java程序中所拋出的異常,是對“異常條件”的封裝、或者說是對調(diào)用者“沒有遵守基本契約”的抗議。異常對象告知方法的調(diào)用者:你(或許是環(huán)境)沒有遵守基本契約。本章將介紹方法執(zhí)行中遇到意外情況時(shí)應(yīng)該如何處理,即Java的異常機(jī)制。為了更好地定義方法接口,本章還介紹了Java的斷言機(jī)制。 8.1 Throwable家族 Java通過面向?qū)ο蟮姆绞教幚懋惓?,最大限度地調(diào)解了程序的正確性和清晰性(可讀性和可維護(hù)性)間的矛盾。8.1.1 異常的概念異常的概念 方法在執(zhí)行時(shí)可能會遇到意外。錯(cuò)誤根源:錯(cuò)誤環(huán)境錯(cuò)誤環(huán)境或非法參數(shù)非法參數(shù)。作為方法的設(shè)計(jì)者,通常希望方法被

3、調(diào)用時(shí)滿足其前置條件,但是,不能夠因?yàn)檎{(diào)用者沒有遵守契約如在網(wǎng)絡(luò)服務(wù)器未啟動時(shí)發(fā)出網(wǎng)絡(luò)連接請求,于是服務(wù)代碼就導(dǎo)致死機(jī)、死循環(huán)或其他后果,而是拋出異常。1. 必須考慮可能發(fā)生的異常事件必須考慮可能發(fā)生的異常事件 服務(wù)的設(shè)計(jì)者,必須考慮到可能發(fā)生的異常事件、必須考慮拋出異常對象、做好本方法的文檔使方法具有良好的接口。方法的設(shè)計(jì)者有義務(wù)對方法參數(shù)的有效性進(jìn)行檢查。不管方法的文檔中是否使用前置條件對參數(shù)加以明確地說明,非法參數(shù)的檢查是方法實(shí)現(xiàn)的第一步。2. 拋出異常拋出異常 if(index=s.length() throw new IndexOutOfBoundsException(); else

4、 return s.charAt(index); 假設(shè)不采用異常對象而使用傳統(tǒng)的錯(cuò)誤處理機(jī)制代碼混雜。功能代碼與錯(cuò)誤處理代碼混雜在一起,嚴(yán)重降低了程序的可讀性。將業(yè)務(wù)邏輯與異常處理分離,可以說是Java異常機(jī)制最重要的目的。同一個(gè)錯(cuò)誤沒有加以數(shù)據(jù)抽象。特殊的返回值問題。3. 何謂異常何謂異常 異常(事件)是指方法執(zhí)行中遇到意外/例外/異常的情況/條件,或者說在方法執(zhí)行時(shí)所發(fā)生的、使正常流程中斷的事件。exception討論源代碼時(shí)所稱的“異?!?,通常指Exception(或它的子類的)對象;當(dāng)說道“異常處理”時(shí),是指對方法執(zhí)行中捕獲的Exception進(jìn)行處理。8.1.2 Error和和Exc

5、eption 當(dāng)程序執(zhí)行遇到exception,程序是就此結(jié)束運(yùn)行還是應(yīng)該從異常事件中恢復(fù)呢?這就得看exception的嚴(yán)重程度。(1)病入膏肓就讓程序安樂死,Error (2)大病小災(zāi)還得救死扶傷,checked Exceptions (3)程序bug引起的(不應(yīng)該出現(xiàn)的異常事件)則不予理會(打電話給編寫那段導(dǎo)致異常代碼的程序員,讓他修改)。RuntimeException 1. java.lang.Error 出現(xiàn)Error,除了盡力使程序安全退出外,不需要做太多的事情(回頭修改源代碼是另一回事)。Error的典型子類有:LinkageError不兼容性問題。ThreadDeath 線程

6、終止錯(cuò)誤VirtualMachineError Java 虛擬機(jī)崩潰InternalError 意外的內(nèi)部錯(cuò)誤OutOfMemoryError 內(nèi)存溢出或沒有可用的內(nèi)存提供給垃圾回收器StackOverflowError 堆棧溢出UnknownError 未知但嚴(yán)重的異常java.io.IOError 發(fā)生嚴(yán)重的 I/O 錯(cuò)誤2. java.lang.ExceptionException分成兩大陣營:RuntimeException和非RuntimeException。 檢查型異常(checked Exceptions),口語化為“必須要處理的異?!?。非檢查異常非檢查異常(Unchecked

7、Exceptions)由程序bug引起,應(yīng) 該 在 程 序 的 調(diào) 試 中 改 正 。 算 術(shù) 運(yùn) 算 異 常ArithmeticException(由除0錯(cuò)等導(dǎo)致)、數(shù)組越界異常ArrayIndexOutOfBoundsException等Exception的典型子類的典型子類 ClassNotFoundException 未找到欲裝載的類CloneNotSupportedException 克隆未實(shí)現(xiàn)Cloneable的對象InterruptedException 線程錯(cuò)誤中斷 IOException 輸入、輸出異常.RuntimeException 運(yùn)行期間拋出的異常Arithmetic

8、Exception 算術(shù)錯(cuò)誤,例如4/0ClassCastException 無效的類型轉(zhuǎn)換IllegalArgumentException 非法參數(shù)IndexOutOfBoundsException 下標(biāo)越界ArrayIndexOutOfBoundsExceptionStringIndexOutOfBoundsExceptionNegativeArraySizeException 用負(fù)數(shù)創(chuàng)建數(shù)組NullPointerException空引用錯(cuò)誤3. 小結(jié)小結(jié) Error:程序員不拋出、不捕捉、不處理。RuntimeException:由系統(tǒng)通過默認(rèn)的異常處理程序自動拋出,自行處理。不強(qiáng)制要求

9、程序員捕捉和處理。調(diào)試程序時(shí)改正。檢查型異常:方法頭中用throws子句聲明,方法體中以throw語句拋出;調(diào)用者以throws子句向上推卸處理責(zé)任、或者使用try-catch捕捉和處理。8.1.3 拋出異常拋出異常 Java程序(包括JDK類庫或第三方包中的代碼)和Java虛擬機(jī)都可能拋出異常。JVM自動拋出的異常:我們不想拋出的,如Error、RuntimeException。下面介紹如何在方法體中手工拋出異常。1. throw語句語句 手工拋出異常,指方法在執(zhí)行過程中遭遇某種異常事件,從而創(chuàng)建相應(yīng)的Throwable對象并拋出。其語法為:throw aThrowableObject;th

10、row new Dog(),程序?qū)o法通過編譯。通常程序中拋出的應(yīng)該是檢查型異常。 異常處理流程一旦執(zhí)行了throw語句,JVM新建一個(gè)異常對象、終止本方法的執(zhí)行流程,返回到方法的調(diào)用者希望得到處理。 如果該異常是檢查型異常,調(diào)用者(1)準(zhǔn)備了catch子句進(jìn)行異常處理;(2)官僚主義地使用throws子句,將異常處理推到調(diào)用者的調(diào)用者。 如果該異常是非檢查異常,調(diào)用者又沒有附加的異常處理代碼,系統(tǒng)將調(diào)用默認(rèn)的異常處理流程,在標(biāo)準(zhǔn)輸出設(shè)備上打印/輸出該異常對象的堆棧使用軌跡。 2. throws子句子句 throws子句在方法頭中說明本方法將拋出的若干異常。它不能獨(dú)立存在,僅僅是方法頭的一部分

11、。 () throws (1)官僚主義官僚主義 本方法作為客戶程序客戶程序,但是不想處理被調(diào)方法拋出的檢查型異常。于是將所有不想處理的異常通過throws子句拋給本方法的調(diào)用者。各種Java書籍在講解IO流、網(wǎng)絡(luò)編程時(shí),為了集中精力,書中的例程常常使用throws以保持代碼的簡短。在實(shí)際編程中,官僚主義地throws是不好的風(fēng)格不好的風(fēng)格。許多程序員經(jīng)常忘記處理異常,或者將異常處理推遲到遙遠(yuǎn)的未來。(2)完善接口完善接口本方法作為服務(wù)程序服務(wù)程序,方法體中使用throw語句拋出的所有檢查型異常所有檢查型異常,必須在方法頭中throws該異常(或者其父類)。換言之,throws子句嚴(yán)格地強(qiáng)制性要

12、求程序員:方法體中只能夠使用throw語句拋出throws子句中聲明的檢查型異常類型或子類型。 對于非檢查型異常,盡管可以不throws,但是為了給調(diào)用者一個(gè)明確的接口,建議也列舉出來。 8.1.4自定義異常類自定義異常類 優(yōu)先使用標(biāo)準(zhǔn)庫的異常。package API.exceptions;public class EmptyQueueException extends Exception public EmptyQueueException(String msg) super(msg); Override public String getMessage()/覆蓋父類的方法 return 隊(duì)

13、列已空,執(zhí)行出隊(duì)操作引發(fā)異常; 3. Exception類簡介類簡介 Exception類的構(gòu)造函數(shù)有2個(gè):vpublic Exception();vpublic Exception(String s); Exception類及其子類從超類Throwable繼承的常用方法有:vpublic String getMessage() /該方法返回一個(gè)詳細(xì)描述異常的字符串。vpublic void printStackTrace( ) /在當(dāng)前的標(biāo)準(zhǔn)輸出(一般就是屏幕)上打印輸出當(dāng)前異常對象的堆棧使用軌跡,也即程序先后調(diào)用執(zhí)行了哪些對象或類的哪些方法,使得運(yùn)行過程中產(chǎn)生了這個(gè)異常對象。vpublic

14、 String toString( ) /該方法返回一個(gè)簡潔描述該異常的字符串。8.2 捕獲和處理捕獲和處理 方法設(shè)計(jì)者使用throws、throw和自定義異常類拋出了異常。方法的使用者則需要捕獲和處理異常。本節(jié)假定使用者不通過throws將異常處理沿調(diào)用鏈向上推卸一般格式一般格式 trym();catch(Exception e)/異常處理語句finally/防止資源泄露說明說明可能拋出異常的語句封裝在try塊中,用以捕獲可能發(fā)生的異常 catch子句分別處理不同類型的異常。Java運(yùn)行時(shí)系統(tǒng)從上到下依次對每個(gè)catch子句處理的異常類型進(jìn)行檢測,直到找到類型相匹配的catch子句為止 無論

15、有無異常發(fā)生,最后都必須執(zhí)行finally塊中的語句 try catch()catch()catch()finally 1. try子句子句 如果被調(diào)的方法m()將throws某些檢查型異常,必須將方法調(diào)用語句封裝在try子句中,表示嘗試執(zhí)行。try子句之后必須至少有一個(gè)catch 或 finally塊,可以同時(shí)有兩者。try子句可能需要多個(gè)catch 塊。異常發(fā)生時(shí),按照書寫順序找到第一個(gè)匹配異常對象類型的catch塊并執(zhí)行。2. catch子句子句 catch子句/塊不能夠獨(dú)立存在,它附屬對應(yīng)的try子句(類似else與if的關(guān)系 。如果執(zhí)行過程中try子句拋出了異常對象x,JVM按照x的

16、類型在catch子句中搜尋匹配的處理代碼。搜索從try后面的第一個(gè)catch子句開始,按照源程序的書寫順序,將x的類型與catch子句的參數(shù)匹配。8.2.2 finally子句 無論try子句拋出或不拋出異常,無論catch子句是否捕獲到異常,finally子句都被執(zhí)行。finally子句是防止資源泄露的關(guān)鍵工具。當(dāng)需要關(guān)閉文件、套接字、流、鎖等資源時(shí),通常將關(guān)閉代碼放在finally子句中以確保資源的釋放,而Java7 引入的try-with-resources語句,為需要關(guān)閉的資源,簡化了代碼。1. finally子句的典型應(yīng)用子句的典型應(yīng)用 (1)多線程程序中 (2)文件處理時(shí) try(

17、 BufferedReader br = new BufferedReader( new FileReader(file) ) 2. finally子句的執(zhí)行流程子句的執(zhí)行流程 如果因?yàn)闄z查型異常退出try,則執(zhí)行相應(yīng)的catch子句,最后執(zhí)行finally子句。如果因?yàn)榉菣z查型異常、或者(官僚主義地)throws的檢查型異常退出try,一般JVM找不到相應(yīng)的catch子句,因而執(zhí)行finally子句然后返回到上級調(diào)用者,進(jìn)一步尋求catch子句。3. try-catch-finally語句中使用語句中使用return finally子句中使用return會嚴(yán)重干擾try和catch的邏輯。除

18、了總是return自己的返回值這一情況外,還會導(dǎo)致某些異常被忽略。8.3 斷言斷言 Java異常機(jī)制的主要目的是保證程序的健壯性,而斷言是調(diào)試、測試程序的一種經(jīng)典方式。斷言失敗則拋出一個(gè)Error子類AssertionError對象。斷言功能在Java 1.4中引入。8.3.1 斷言的語義和語法 斷言斷言(assertion)是有真值的陳述句。Java斷言的語義為:一個(gè)正確程序必須保證斷言句為真。如果程序執(zhí)行時(shí)計(jì)算它為false,則說明程序已經(jīng)處于不正確的狀態(tài),系統(tǒng)將顯示某個(gè)警告或消息字符串并終止程序的執(zhí)行。 1. 斷言語句斷言語句 Java中斷言語句有兩種形式:assert anAssert

19、ion;assert anAssertion: expression;anAssertion是一個(gè)boolean表達(dá)式。如果anAssertion的值為false,該語句將拋出一個(gè)AssertionError對象。2. 語法例子語法例子 package API.assertions;public class AssertionDemo private String name; private static char charAt(int index ,String s) assert !( index=s.length() :自己設(shè)計(jì)的private方法還瞎調(diào)用!真是佩服自己; return

20、s.charAt(index); public static void test(int index) String s = yqj2065; char c = charAt(index,s);/取 -1、2、7 System.out.println(c + is index +index+ of +s); assert false:如果前面沒有遇到AssertionError,輸入index-1; 3. 開啟開啟/關(guān)閉斷言功能關(guān)閉斷言功能 為了提高性能,默認(rèn)狀態(tài)下JVM關(guān)閉斷言功能。 要開啟斷言功能,可以:含有斷言語句的Java程序編譯后,在控制臺中,以java -ea開啟斷言功能。Java

21、程序種調(diào)用ClassLoader類的若干方法,在程序運(yùn)行中動態(tài)地開啟和關(guān)閉斷言功能。為了學(xué)習(xí)的方便,BlueJ 3.0.8默認(rèn)狀態(tài)下打開了斷言功能。 8.3.2 斷言的使用指南斷言的使用指南 斷言機(jī)制用于檢查程序的內(nèi)部正確性,不得干擾public方法的接口或替代其參數(shù)檢查。顯式地使用斷言,檢查一些關(guān)鍵的值(這些值對整個(gè)程序,或者局部功能的完成有很大的影響),以便于更容易地找到程序的錯(cuò)誤。斷言機(jī)制是調(diào)試、測試程序的一種經(jīng)典手段斷言機(jī)制是調(diào)試、測試程序的一種經(jīng)典手段。斷言的布爾表達(dá)式應(yīng)該短小、易懂。如果需要計(jì)算的表達(dá)式很復(fù)雜,應(yīng)該使用方法。斷言用于檢查程序運(yùn)行中的不變式(invariants)。不

22、變式為程序運(yùn)行中永遠(yuǎn)為真的條件。例如零和游戲中,一方所贏正是另一方所輸,游戲的總成績永遠(yuǎn)是零。斷言用于檢查方法的后置條件。 正方形正方形 is a 長方形長方形?public class Rectangle private double height; /高 private double width; /private double S;/面積S void setW(double w) width=w; void setH(double h) height=h; double getH() return height; double getW() return width; double getS() return height*width;double單純的單純的使用使用extends僅僅使用extends建立繼承關(guān)系,問題是:1、 2、 Square繼承的height、width非常多余(想象一下在CAD/CAE程序中,成千上萬的正方形對象的情景。大量浪費(fèi)內(nèi)存空間)?!静簧罹俊?、Square1不能夠替代Rectangle。不變式不變式 W = H Rectangle的s

溫馨提示

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

評論

0/150

提交評論