Java 異常(Java Exception)(三)

4.2 拋出異常

任何Java代碼都可以拋出異常,如:自己編寫的代碼沿彭、來自Java開發(fā)環(huán)境包中代碼,或者Java運(yùn)行時(shí)系統(tǒng)朦佩。無論是誰并思,都可以通過Java的throw語句拋出異常。從方法中拋出的任何異常都必須使用throws子句语稠。

1. throws拋出異常

如果一個(gè)方法可能會(huì)出現(xiàn)異常宋彼,但沒有能力處理這種異常,可以在方法聲明處用throws子句來聲明拋出異常仙畦。例如汽車在運(yùn)行時(shí)可能會(huì)出現(xiàn)故障输涕,汽車本身沒辦法處理這個(gè)故障,那就讓開車的人來處理慨畸。
throws語句用在方法定義時(shí)聲明該方法要拋出的異常類型莱坎,如果拋出的是Exception異常類型,則該方法被聲明為拋出所有的異常寸士。多個(gè)異抽苁玻可使用逗號(hào)分割碴卧。throws語句的語法格式為:

methodname throws Exception1,Exception2,..,ExceptionN  
{  
}

方法名后的throws Exception1,Exception2,...,ExceptionN 為聲明要拋出的異常列表。當(dāng)方法拋出異常列表的異常時(shí)乃正,方法將不對(duì)這些類型及其子類類型的異常作處理住册,而拋向調(diào)用該方法的方法,由他去處理瓮具。例如:

import java.lang.Exception;  
public class TestException {  
    static void pop() throws NegativeArraySizeException {  
        // 定義方法并拋出NegativeArraySizeException異常  
        int[] arr = new int[-3]; // 創(chuàng)建數(shù)組  
    }  
  
    public static void main(String[] args) { // 主方法  
        try { // try語句處理異常信息  
            pop(); // 調(diào)用pop()方法  
        } catch (NegativeArraySizeException e) {  
            System.out.println("pop()方法拋出的異常");// 輸出異常信息  
        }  
    }  
  
} 

使用throws關(guān)鍵字將異常拋給調(diào)用者后荧飞,如果調(diào)用者不想處理該異常,可以繼續(xù)向上拋出名党,但最終要有能夠處理該異常的調(diào)用者叹阔。
pop方法沒有處理異常NegativeArraySizeException,而是由main函數(shù)來處理兑巾。

Throws拋出異常的規(guī)則:

  1. 如果是不可查異常(unchecked exception)条获,即Error、RuntimeException或它們的子類蒋歌,那么可以不使用throws關(guān)鍵字來聲明要拋出的異常帅掘,編譯仍能順利通過,但在運(yùn)行時(shí)會(huì)被系統(tǒng)拋出堂油。

2)必須聲明方法可拋出的任何可查異常(checked exception)修档。即如果一個(gè)方法可能出現(xiàn)受可查異常,要么用try-catch語句捕獲府框,要么用throws子句聲明將它拋出吱窝,否則會(huì)導(dǎo)致編譯錯(cuò)誤

3)僅當(dāng)拋出了異常,該方法的調(diào)用者才必須處理或者重新拋出該異常迫靖。當(dāng)方法的調(diào)用者無力處理該異常的時(shí)候院峡,應(yīng)該繼續(xù)拋出,而不是囫圇吞棗系宜。

4)調(diào)用方法必須遵循任何可查異常的處理和聲明規(guī)則照激。若覆蓋一個(gè)方法,則不能聲明與覆蓋方法不同的異常盹牧。聲明的任何異常必須是被覆蓋方法所聲明異常的同類或子類俩垃。

例如:

void method1() throws IOException{}  //合法    
   
//編譯錯(cuò)誤,必須捕獲或聲明拋出IOException    
void method2(){    
  method1();    
}    
   
//合法汰寓,聲明拋出IOException    
void method3()throws IOException {    
  method1();    
}    
   
//合法口柳,聲明拋出Exception,IOException是Exception的子類    
void method4()throws Exception {    
  method1();    
}    
   
//合法有滑,捕獲IOException    
void method5(){    
 try{    
    method1();    
 }catch(IOException e){…}    
}    
   
//編譯錯(cuò)誤跃闹,必須捕獲或聲明拋出Exception    
void method6(){    
  try{    
    method1();    
  }catch(IOException e){throw new Exception();}    
}    
   
//合法,聲明拋出Exception    
void method7()throws Exception{    
 try{    
  method1();    
 }catch(IOException e){throw new Exception();}    
}  

** 判斷一個(gè)方法可能會(huì)出現(xiàn)異常的依據(jù)如下:**
1)方法中有throw語句。例如辣卒,以上method7()方法的catch代碼塊有throw語句掷贾。
2)調(diào)用了其他方法,其他方法用throws子句聲明拋出某種異常荣茫。例如想帅,method3()方法調(diào)用了method1()方法,method1()方法聲明拋出IOException啡莉,因此港准,在method3()方法中可能會(huì)出現(xiàn)IOException。

2. 使用throw拋出異常

throw總是出現(xiàn)在函數(shù)體中咧欣,用來拋出一個(gè)Throwable類型的異常浅缸。程序會(huì)在throw語句后立即終止,它后面的語句執(zhí)行不到魄咕,然后在包含它的所有try塊中(可能在上層調(diào)用函數(shù)中)從里向外尋找含有與其匹配的catch子句的try塊衩椒。
  我們知道,異常是異常類的實(shí)例對(duì)象哮兰,我們可以創(chuàng)建異常類的實(shí)例對(duì)象通過throw語句拋出毛萌。該語句的語法格式為:
throw new exceptionname;
例如拋出一個(gè)IOException類的異常對(duì)象:
throw new IOException;
要注意的是,throw 拋出的只能夠是可拋出類Throwable 或者其子類的實(shí)例對(duì)象喝滞。下面的操作是錯(cuò)誤的:
throw new String("exception");

這是因?yàn)镾tring 不是Throwable 類的子類阁将。

如果拋出了檢查異常,則還應(yīng)該在方法頭部聲明方法可能拋出的異常類型右遭。該方法的調(diào)用者也必須檢查處理拋出的異常做盅。

如果所有方法都層層上拋獲取的異常,最終JVM會(huì)進(jìn)行處理窘哈,處理也很簡單吹榴,就是打印異常消息和堆棧信息。如果拋出的是Error或RuntimeException滚婉,則該方法的調(diào)用者可選擇處理該異常腊尚。

package Test;  
import java.lang.Exception;  
public class TestException {  
    static int quotient(int x, int y) throws MyException { // 定義方法拋出異常  
        if (y < 0) { // 判斷參數(shù)是否小于0  
            throw new MyException("除數(shù)不能是負(fù)數(shù)"); // 異常信息  
        }  
        return x/y; // 返回值  
    }  
    public static void main(String args[]) { // 主方法  
        int  a =3;  
        int  b =0;   
        try { // try語句包含可能發(fā)生異常的語句  
            int result = quotient(a, b); // 調(diào)用方法quotient()  
        } catch (MyException e) { // 處理自定義異常  
            System.out.println(e.getMessage()); // 輸出異常信息  
        } catch (ArithmeticException e) { // 處理ArithmeticException異常  
            System.out.println("除數(shù)不能為0"); // 輸出提示信息  
        } catch (Exception e) { // 處理其他異常  
            System.out.println("程序發(fā)生了其他的異常"); // 輸出提示信息  
        }  
    }  
  
}  
class MyException extends Exception { // 創(chuàng)建自定義異常類  
    String message; // 定義String類型變量  
    public MyException(String ErrorMessagr) { // 父類方法  
        message = ErrorMessagr;  
    }  
  
    public String getMessage() { // 覆蓋getMessage()方法  
        return message;  
    }  
}  

4.3 異常鏈

  1. 如果調(diào)用quotient(3,-1),將發(fā)生MyException異常满哪,程序調(diào)轉(zhuǎn)到catch (MyException e)代碼塊中執(zhí)行;

  2. 如果調(diào)用quotient(5,0)劝篷,將會(huì)因“除數(shù)為0”錯(cuò)誤引發(fā)ArithmeticException異常哨鸭,屬于運(yùn)行時(shí)異常類,由Java運(yùn)行時(shí)系統(tǒng)自動(dòng)拋出娇妓。quotient()方法沒有捕捉ArithmeticException異常像鸡,Java運(yùn)行時(shí)系統(tǒng)將沿方法調(diào)用棧查到main方法,將拋出的異常上傳至quotient()方法的調(diào)用者:

    int result = quotient(a, b); // 調(diào)用方法quotient()
    由于該語句在try監(jiān)控區(qū)域內(nèi),因此傳回的“除數(shù)為0”的ArithmeticException異常由Java運(yùn)行時(shí)系統(tǒng)拋出只估,并匹配catch子句:

    catch (ArithmeticException e) { // 處理ArithmeticException異常 System.out.println("除數(shù)不能為0"); // 輸出提示信息 }

    處理結(jié)果是輸出“除數(shù)不能為0”志群。Java這種向上傳遞異常信息的處理機(jī)制,形成異常鏈蛔钙。

    Java方法拋出的可查異常將依據(jù)調(diào)用棧锌云、沿著方法調(diào)用的層次結(jié)構(gòu)一直傳遞到具備處理能力的調(diào)用方法,最高層次到main方法為止吁脱。如果異常傳遞到main方法桑涎,而main不具備處理能力,也沒有通過throws聲明拋出該異常兼贡,將可能出現(xiàn)編譯錯(cuò)誤攻冷。

    3)如還有其他異常發(fā)生,將使用catch (Exception e)捕捉異常遍希。由于Exception是所有異常類的父類等曼,如果將catch (Exception e)代碼塊放在其他兩個(gè)代碼塊的前面,后面的代碼塊將永遠(yuǎn)得不到執(zhí)行凿蒜,就沒有什么意義了禁谦,所以catch語句的順序不可掉換。

4.4 Throwable類中的常用方法

注意:catch關(guān)鍵字后面括號(hào)中的Exception類型的參數(shù)e篙程。Exception就是try代碼塊傳遞給catch代碼塊的變量類型枷畏,e就是變量名。catch代碼塊中語句"e.getMessage();"用于輸出錯(cuò)誤性質(zhì)虱饿。通常異常處理常用3個(gè)函數(shù)來獲取異常的有關(guān)信息:

getCause():返回拋出異常的原因拥诡。如果 cause 不存在或未知,則返回 null氮发。

getMeage():返回異常的消息信息渴肉。

printStackTrace():對(duì)象的堆棧跟蹤輸出至錯(cuò)誤輸出流,作為字段 System.err 的值爽冕。

有時(shí)為了簡單會(huì)忽略掉catch語句后的代碼仇祭,這樣try-catch語句就成了一種擺設(shè),一旦程序在運(yùn)行過程中出現(xiàn)了異常颈畸,就會(huì)忽略處理異常乌奇,而錯(cuò)誤發(fā)生的原因很難查找。

5.Java常見異常

在Java中提供了一些異常用來描述經(jīng)常發(fā)生的錯(cuò)誤眯娱,對(duì)于這些異常礁苗,有的需要程序員進(jìn)行捕獲處理或聲明拋出,有的是由Java虛擬機(jī)自動(dòng)進(jìn)行捕獲處理徙缴。Java中常見的異常類:

1. runtimeException子類:

1试伙、 java.lang.ArrayIndexOutOfBoundsException 數(shù)組索引越界異常。當(dāng)對(duì)數(shù)組的索引值為負(fù)數(shù)或大于等于數(shù)組大小時(shí)拋出。 2疏叨、java.lang.ArithmeticException 算術(shù)條件異常潘靖。譬如:整數(shù)除零等。 3蚤蔓、java.lang.NullPointerException 空指針異常卦溢。當(dāng)應(yīng)用試圖在要求使用對(duì)象的地方使用了null時(shí),拋出該異常昌粤。譬如:調(diào)用null對(duì)象的實(shí)例方法既绕、訪問null對(duì)象的屬性、計(jì)算null對(duì)象的長度涮坐、使用throw語句拋出null等等 4凄贩、java.lang.ClassNotFoundException 找不到類異常。當(dāng)應(yīng)用試圖根據(jù)字符串形式的類名構(gòu)造類袱讹,而在遍歷CLASSPAH之后找不到對(duì)應(yīng)名稱的class文件時(shí)疲扎,拋出該異常。

5捷雕、java.lang.NegativeArraySizeException 數(shù)組長度為負(fù)異常

6椒丧、java.lang.ArrayStoreException 數(shù)組中包含不兼容的值拋出的異常

7、java.lang.SecurityException 安全性異常

8救巷、java.lang.IllegalArgumentException 非法參數(shù)異常

2.IOException

IOException:操作輸入流和輸出流時(shí)可能出現(xiàn)的異常壶熏。

EOFException 文件已結(jié)束異常

FileNotFoundException 文件未找到異常

  1. 其他

ClassCastException 類型轉(zhuǎn)換異常類

ArrayStoreException 數(shù)組中包含不兼容的值拋出的異常

SQLException 操作[數(shù)據(jù)庫]異常類

NoSuchFieldException 字段未找到異常

NoSuchMethodException 方法未找到拋出的異常

NumberFormatException 字符串轉(zhuǎn)換為數(shù)字拋出的異常

StringIndexOutOfBoundsException 字符串索引超出范圍拋出的異常

IllegalAccessException 不允許訪問某類異常

InstantiationException 當(dāng)應(yīng)用程序試圖使用Class類中的newInstance()方法創(chuàng)建一個(gè)類的實(shí)例,而指定的類對(duì)象無法被實(shí)例化時(shí)浦译,拋出該異常

6.自定義異常

使用Java內(nèi)置的異常類可以描述在編程時(shí)出現(xiàn)的大部分異常情況棒假。除此之外,用戶還可以自定義異常精盅。用戶自定義異常類帽哑,只需繼承Exception類即可。 在程序中使用自定義異常類叹俏,大體可分為以下幾個(gè)步驟妻枕。 (1)創(chuàng)建自定義異常類。 (2)在方法中通過throw關(guān)鍵字拋出異常對(duì)象粘驰。 (3)如果在當(dāng)前拋出異常的方法中處理異常屡谐,可以使用try-catch語句捕獲并處理;否則在方法的聲明處通過throws關(guān)鍵字指明要拋出給方法調(diào)用者的異常蝌数,繼續(xù)進(jìn)行下一步操作康嘉。 (4)在出現(xiàn)異常方法的調(diào)用者中捕獲并處理異常。

在上面的“使用throw拋出異匙亚埃”例子已經(jīng)提到了。

歡迎加入學(xué)習(xí)交流群569772982,大家一起學(xué)習(xí)交流枝哄。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末肄梨,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子挠锥,更是在濱河造成了極大的恐慌众羡,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,542評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蓖租,死亡現(xiàn)場(chǎng)離奇詭異粱侣,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)蓖宦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,596評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門齐婴,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人稠茂,你說我怎么就攤上這事柠偶。” “怎么了睬关?”我有些...
    開封第一講書人閱讀 158,021評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵诱担,是天一觀的道長。 經(jīng)常有香客問我电爹,道長蔫仙,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,682評(píng)論 1 284
  • 正文 為了忘掉前任丐箩,我火速辦了婚禮摇邦,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘雏蛮。我一直安慰自己涎嚼,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,792評(píng)論 6 386
  • 文/花漫 我一把揭開白布挑秉。 她就那樣靜靜地躺著法梯,像睡著了一般。 火紅的嫁衣襯著肌膚如雪犀概。 梳的紋絲不亂的頭發(fā)上立哑,一...
    開封第一講書人閱讀 49,985評(píng)論 1 291
  • 那天,我揣著相機(jī)與錄音姻灶,去河邊找鬼铛绰。 笑死,一個(gè)胖子當(dāng)著我的面吹牛产喉,可吹牛的內(nèi)容都是我干的捂掰。 我是一名探鬼主播敢会,決...
    沈念sama閱讀 39,107評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼这嚣!你這毒婦竟也來了鸥昏?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,845評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤姐帚,失蹤者是張志新(化名)和其女友劉穎吏垮,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體罐旗,經(jīng)...
    沈念sama閱讀 44,299評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡膳汪,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,612評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了九秀。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片遗嗽。...
    茶點(diǎn)故事閱讀 38,747評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖颤霎,靈堂內(nèi)的尸體忽然破棺而出媳谁,到底是詐尸還是另有隱情,我是刑警寧澤友酱,帶...
    沈念sama閱讀 34,441評(píng)論 4 333
  • 正文 年R本政府宣布晴音,位于F島的核電站,受9級(jí)特大地震影響缔杉,放射性物質(zhì)發(fā)生泄漏锤躁。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,072評(píng)論 3 317
  • 文/蒙蒙 一或详、第九天 我趴在偏房一處隱蔽的房頂上張望系羞。 院中可真熱鬧,春花似錦霸琴、人聲如沸椒振。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,828評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽澎迎。三九已至,卻和暖如春选调,著一層夾襖步出監(jiān)牢的瞬間夹供,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,069評(píng)論 1 267
  • 我被黑心中介騙來泰國打工仁堪, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留哮洽,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,545評(píng)論 2 362
  • 正文 我出身青樓弦聂,卻偏偏與公主長得像鸟辅,于是被迫代替她去往敵國和親氛什。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,658評(píng)論 2 350

推薦閱讀更多精彩內(nèi)容

  • Java異常類型 所有異常類型都是Throwable的子類匪凉,Throwable把異常分成兩個(gè)不同分支的子類Erro...
    予別她閱讀 924評(píng)論 0 2
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法屉更,類相關(guān)的語法,內(nèi)部類的語法洒缀,繼承相關(guān)的語法,異常的語法欺冀,線程的語...
    子非魚_t_閱讀 31,602評(píng)論 18 399
  • JAVA異常與異常處理詳解 一树绩、異常簡介 什么是異常? 異常就是有異于常態(tài)隐轩,和正常情況不一樣饺饭,有錯(cuò)誤出錯(cuò)。在jav...
    java大濕兄閱讀 995評(píng)論 0 11
  • 通俗編程——白話JAVA異常機(jī)制 - 代碼之道职车,編程之法 - 博客頻道 - CSDN.NEThttp://blog...
    葡萄喃喃囈語閱讀 3,174評(píng)論 0 25
  • 你一天要刷多少次朋友圈悴灵? 微信這個(gè)神奇的小東西就像撬動(dòng)地球的那根杠桿一樣扛芽,撬動(dòng)了普羅大眾的通信方式。朋友圈更是給了...
    廢柴姑娘戴紅花閱讀 261評(píng)論 0 0