1.10 throws和throw:声明和抛出异常
Java 中的異常處理除了捕獲異常和處理異常之外,還包括聲明異常和拋出異常。
實(shí)現(xiàn)聲明和拋出異常的關(guān)鍵字非常相似,它們是 throws 和 throw。
可以通過(guò) throws 關(guān)鍵字在方法上聲明該方法要拋出的異常,然后在方法內(nèi)部通過(guò) throw 拋出異常對(duì)象。
本節(jié)詳細(xì)介紹在 Java 中如何聲明異常和拋出異常。
throws 聲明異常
當(dāng)一個(gè)方法產(chǎn)生一個(gè)它不處理的異常時(shí),那么就需要在該方法的頭部聲明這個(gè)異常,以便將該異常傳遞到方法的外部進(jìn)行處理。使用 throws 聲明的方法表示此方法不處理異常。throws 具體格式如下:
returnType method_name(paramList) throws Exception 1,Exception2,…{…}其中,returnType 表示返回值類(lèi)型;method_name 表示方法名;paramList 表示參數(shù)列表;Exception 1,Exception2,… 表示異常類(lèi)。
如果有多個(gè)異常類(lèi),它們之間用逗號(hào)分隔。這些異常類(lèi)可以是方法中調(diào)用了可能拋出異常的方法而產(chǎn)生的異常,也可以是方法體中生成并拋出的異常。
使用 throws 聲明拋出異常的思路是,當(dāng)前方法不知道如何處理這種類(lèi)型的異常,該異常應(yīng)該由向上一級(jí)的調(diào)用者處理;如果 main 方法也不知道如何處理這種類(lèi)型的異常,也可以使用 throws 聲明拋出異常,該異常將交給 JVM 處理。JVM 對(duì)異常的處理方法是,打印異常的跟蹤棧信息,并中止程序運(yùn)行,這就是前面程序在遇到異常后自動(dòng)結(jié)束的原因。
例 1
創(chuàng)建一個(gè) readFile() 方法,該方法用于讀取文件內(nèi)容,在讀取的過(guò)程中可能會(huì)產(chǎn)生 IOException 異常,但是在該方法中不做任何的處理,而將可能發(fā)生的異常交給調(diào)用者處理。在 main() 方法中使用 try catch 捕獲異常,并輸出異常信息。代碼如下:
以上代碼,首先在定義 readFile() 方法時(shí)用 throws 關(guān)鍵字聲明在該方法中可能產(chǎn)生的異常,然后在 main() 方法中調(diào)用 readFile() 方法,并使用 catch 語(yǔ)句捕獲產(chǎn)生的異常。
方法重寫(xiě)時(shí)聲明拋出異常的限制
使用 throws 聲明拋出異常時(shí)有一個(gè)限制,是方法重寫(xiě)中的一條規(guī)則:子類(lèi)方法聲明拋出的異常類(lèi)型應(yīng)該是父類(lèi)方法聲明拋出的異常類(lèi)型的子類(lèi)或相同,子類(lèi)方法聲明拋出的異常不允許比父類(lèi)方法聲明拋出的異常多。看如下程序。
使用 throws 聲明拋出異常時(shí)有一個(gè)限制,是方法重寫(xiě)中的一條規(guī)則:子類(lèi)方法聲明拋出的異常類(lèi)型應(yīng)該是父類(lèi)方法聲明拋出的異常類(lèi)型的子類(lèi)或相同,子類(lèi)方法聲明拋出的異常不允許比父類(lèi)方法聲明拋出的異常多。看如下程序。
上面程序中 Sub 子類(lèi)中的 test() 方法聲明拋出 Exception,該 Exception 是其父類(lèi)聲明拋出異常 IOException 類(lèi)的父類(lèi),這將導(dǎo)致程序無(wú)法通過(guò)編譯。
所以在編寫(xiě)類(lèi)繼承代碼時(shí)要注意,子類(lèi)在重寫(xiě)父類(lèi)帶 throws 子句的方法時(shí),子類(lèi)方法聲明中的 throws 子句不能出現(xiàn)父類(lèi)對(duì)應(yīng)方法的 throws 子句中沒(méi)有的異常類(lèi)型,因此 throws 子句可以限制子類(lèi)的行為。也就是說(shuō),子類(lèi)方法拋出的異常不能超過(guò)父類(lèi)定義的范圍。
throw 拋出異常
與 throws 不同的是,throw 語(yǔ)句用來(lái)直接拋出一個(gè)異常,后接一個(gè)可拋出的異常類(lèi)對(duì)象,其語(yǔ)法格式如下:
throw ExceptionObject;其中,ExceptionObject 必須是 Throwable 類(lèi)或其子類(lèi)的對(duì)象。如果是自定義異常類(lèi),也必須是 Throwable 的直接或間接子類(lèi)。例如,以下語(yǔ)句在編譯時(shí)將會(huì)產(chǎn)生語(yǔ)法錯(cuò)誤:
throw new String("拋出異常"); // String類(lèi)不是Throwable類(lèi)的子類(lèi)當(dāng) throw 語(yǔ)句執(zhí)行時(shí),它后面的語(yǔ)句將不執(zhí)行,此時(shí)程序轉(zhuǎn)向調(diào)用者程序,尋找與之相匹配的 catch 語(yǔ)句,執(zhí)行相應(yīng)的異常處理程序。如果沒(méi)有找到相匹配的 catch 語(yǔ)句,則再轉(zhuǎn)向上一層的調(diào)用程序。這樣逐層向上,直到最外層的異常處理程序終止程序并打印出調(diào)用棧情況。
throw 關(guān)鍵字不會(huì)單獨(dú)使用,它的使用完全符合異常的處理機(jī)制,但是,一般來(lái)講用戶都在避免異常的產(chǎn)生,所以不會(huì)手工拋出一個(gè)新的異常類(lèi)的實(shí)例,而往往會(huì)拋出程序中已經(jīng)產(chǎn)生的異常類(lèi)的實(shí)例。
例 2
在某倉(cāng)庫(kù)管理系統(tǒng)中,要求管理員的用戶名需要由 8 位以上的字母或者數(shù)字組成,不能含有其他的字符。當(dāng)長(zhǎng)度在 8 位以下時(shí)拋出異常,并顯示異常信息;當(dāng)字符含有非字母或者數(shù)字時(shí),同樣拋出異常,顯示異常信息。代碼如下:
如上述代碼,在 validateUserName() 方法中兩處拋出了 IllegalArgumentException 異常,即當(dāng)用戶名字符含有非字母或者數(shù)字以及長(zhǎng)度不夠 8 位時(shí)。在 main() 方法中,調(diào)用了 validateUserName() 方法,并使用 catch 語(yǔ)句捕獲該方法可能拋出的異常。
運(yùn)行程序,當(dāng)用戶輸入的用戶名包含非字母或者數(shù)字的字符時(shí),程序輸出異常信息,如下所示。
請(qǐng)輸入用戶名: ligulasizhaosi!!!!!! java.lang.IllegalArgumentException: 用戶名只能由字母和數(shù)字組成!當(dāng)用戶輸入的用戶名長(zhǎng)度不夠 8 位時(shí),程序同樣會(huì)輸出異常信息,如下所示。
請(qǐng)輸入用戶名: admin java.lang.IllegalArgumentException: 用戶名長(zhǎng)度必須大于 8 位!throws 關(guān)鍵字和 throw 關(guān)鍵字在使用上的幾點(diǎn)區(qū)別如下:
- throws 用來(lái)聲明一個(gè)方法可能拋出的所有異常信息,表示出現(xiàn)異常的一種可能性,但并不一定會(huì)發(fā)生這些異常;throw
則是指拋出的一個(gè)具體的異常類(lèi)型,執(zhí)行 throw 則一定拋出了某種異常對(duì)象。 - 通常在一個(gè)方法(類(lèi))的聲明處通過(guò) throws 聲明方法(類(lèi))可能拋出的異常信息,而在方法(類(lèi))內(nèi)部通過(guò) throw
聲明一個(gè)具體的異常信息。 - throws 通常不用顯示地捕獲異常,可由系統(tǒng)自動(dòng)將所有捕獲的異常信息拋給上級(jí)方法; throw
則需要用戶自己捕獲相關(guān)的異常,而后再對(duì)其進(jìn)行相關(guān)包裝,最后將包裝后的異常信息拋出。
總結(jié)
以上是生活随笔為你收集整理的1.10 throws和throw:声明和抛出异常的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 1.9 Java 9增强的自动资源管理
- 下一篇: 1.11 多异常捕获