Day6—異常處理

異常體系

異常體系結(jié)構(gòu)
Error

Java虛擬機(jī)無法解決的嚴(yán)重問題。如:JVM系統(tǒng)內(nèi)部錯(cuò)誤、資源耗盡等嚴(yán)重情況烟勋。比如:StackOverflowError和OOM。一般不編寫針對性的代碼進(jìn)行處理筐付。

    public static void main(String[] args) {
        // error:
        // 棧溢出 java.lang.StackOverflowError
        main(args);
        
        // 堆溢出 java.lang.OutOfMemoryError
        Integer[] arr = new Integer[1024*1024*1024];    
    }
Exception

其它因編程錯(cuò)誤或偶然的外在因素導(dǎo)致的一般性問題卵惦,可以使用針對性的代碼進(jìn)行處理。例如:

  • 空指針訪問
  • 試圖讀取不存在的文件
  • 網(wǎng)絡(luò)連接中斷
  • 數(shù)組角標(biāo)越界

Exception可分為編譯時(shí)異常與運(yùn)行時(shí)異常

編譯時(shí)異常(受檢異常):

  • 是指編譯器要求必須處置的異常瓦戚。即程序在運(yùn)行時(shí)由于外界因素造成的一般性異常沮尿。編譯器要求Java程序必須捕獲或聲明所有編譯時(shí)異常。
  • 對于這類異常伤极,如果程序不處理蛹找,可能會帶來意想不到的結(jié)果姨伤。

運(yùn)行時(shí)異常(非受檢異常):

  • 是指編譯器不要求強(qiáng)制處置的異常哨坪。一般是指編程時(shí)的邏輯錯(cuò)誤,是程序員應(yīng)該積極避免其出現(xiàn)的異常乍楚。java.lang.RuntimeException類及它的子類都是運(yùn)行時(shí)異常当编。
  • 對于這類異常,可以不作處理徒溪,因?yàn)檫@類異常很普遍忿偷,若全處理可能會對程序的可讀性和運(yùn)行效率產(chǎn)生影響。

常見異常

空指針異常 NullPointerException
@Test
    public void test1(){
        int[] arr = null;
        int num = arr[1];
    }
數(shù)組/字符串角標(biāo)越界 ArrayIndexOutOfBoundsException / StringIndexOutOfBoundsException
@Test
    public void test2(){
        String str = "abc";
        char c = str.charAt(3);
    }
    
類轉(zhuǎn)換異常 ClassCastException
    @Test
    public void test3(){
        Object obj = new Date();
        String str = (String)obj;
    }
數(shù)學(xué)運(yùn)算異常 ArithmeticException
@Test
    public void test4(){
        int i = 10;
        int j = 0;
        int num = i / j;
    }
數(shù)字格式化異常 NumberFormatException
@Test
    public void test5(){
        String s = "abc";
        int num = Integer.parseInt(s);
        System.out.println(num);
    }

異常處理1:try-catch-finally

java異常處理采用“抓拋模型”:

  • 過程一臊泌,拋:程序正常執(zhí)行過程中鲤桥,一旦出現(xiàn)異常,就會在異常代碼處生成一個(gè)對應(yīng)的異常對象并將此對象拋出渠概。一旦拋出對象以后茶凳,其后的代碼不再執(zhí)行
  • 過程二,抓:異常處理的方式 try_catch_finally 或 throws
  try{
  
        // 可能出現(xiàn)異常的代碼
  
  }catch(異常類型1 變量名1){
  
        // 處理異常的方式1
  
  }catch(異常類型2 變量名2){
  
        // 處理異常的方式2
  }
  ...
  finally{
  
        // 一定會執(zhí)行的代碼
  
  }

try_catch:

  • 1播揪、finally是可選的
  • 2贮喧、使用try將可能出現(xiàn)異常的代碼包裝起來,在執(zhí)行過程中猪狈,一旦出現(xiàn)異常箱沦,就會生成一個(gè)對應(yīng)異常類的對象根據(jù)此對象的類型,去catch中進(jìn)行匹配
  • 3雇庙、一旦try中的異常對象匹配到某一個(gè)catch時(shí)谓形,就進(jìn)入到catch中進(jìn)行異常處理灶伊。一旦處理完成,就跳出當(dāng)前的try-catch結(jié)構(gòu)(在沒有finally的情況下)寒跳。繼續(xù)執(zhí)行其后的代碼
  • 4梅鹦、catch中的異常類型如果沒有子父類關(guān)系求妹,則其聲明順序沒有要求;catch中的異常類型如果有子父類關(guān)系,則要求子類一定在父類上面悼院,否則會報(bào)錯(cuò)
  • 5、常用的異常對象處理的方式:
    - sysout String
    - getMessage()
    - printStackTrace()
  • 6半开、 在try結(jié)構(gòu)中聲明的變量混滔,出了try結(jié)構(gòu)以后便無法繼續(xù)使用

finally:

  • 1、finally是可選的
  • 2征冷、finally中聲明的是一定會執(zhí)行的代碼择膝。即使catch中又出現(xiàn)異常,又或者try检激、catch中出現(xiàn)return語句等情況
  • 3肴捉、數(shù)據(jù)庫連接、輸入輸出流叔收、網(wǎng)絡(luò)編程中的socket資源等齿穗,jvm是無法自動回收的,需要手動進(jìn)行釋放操作饺律,此操作需要在finally中進(jìn)行
  • 4窃页、try_catch_finally可以進(jìn)行嵌套
public void test2(){
        FileInputStream fis = null;
        try {
            File file = new File("hello.txt");
            fis = new FileInputStream(file);
                
            int data = fis.read();
            while(data != -1){
                System.out.print((char)data);
                data = fis.read();
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            try {
                if(fis != null)
                    fis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

體會1:使用try_catch_finally處理編譯時(shí)異常,使得程序在編譯階段不會報(bào)錯(cuò)复濒;但程序在運(yùn)行時(shí)仍然有可能報(bào)錯(cuò)脖卖;相當(dāng)于用try_catch_finally將一個(gè)編譯時(shí)可能出現(xiàn)的異常,延遲到了運(yùn)行時(shí)出現(xiàn)

體會2:由于開發(fā)中運(yùn)行時(shí)異常比較常見巧颈,我們不會編寫針對它的異常處理畦木;對于編譯時(shí)異常,我們才會考慮其異常處理

異常處理2:throws

throws + 異常類型
寫在方法聲明處砸泛,指明當(dāng)方法執(zhí)行時(shí)十籍,可能拋出的異常類型
一旦該方法體執(zhí)行時(shí),出現(xiàn)異常晾嘶,仍會在異常代碼處生成一個(gè)異常類的對象妓雾,此對象滿足throws后面的異常類型時(shí),就會被拋出垒迂。并且后續(xù)的代碼不會被執(zhí)行
總的來說械姻,try_catch_finally會確實(shí)地將異常給處理掉,而throws只是將異常拋給了方法的調(diào)用者,并沒有真正處理異常

public class Throws {
    
    public static void main(String[] args) {
        try{
            method2();
        }catch(FileNotFoundException e){
            e.printStackTrace();
        }catch(IOException e){
            e.printStackTrace();
        }
    }
    
    public static void method2() throws FileNotFoundException,IOException{
        method();
    }
    
    public static void method() throws FileNotFoundException,IOException{
        File file = new File("hello.txt");
        FileInputStream fis = new FileInputStream(file);
                
        int data = fis.read();
        while(data != -1){
            System.out.print((char)data);
            data = fis.read();
        }
            
        fis.close();

    }
}

手動拋出異常:throw

Java異常類對象除在程序執(zhí)行過程中出現(xiàn)異常時(shí)由系統(tǒng)自動生成并拋出楷拳,也可根據(jù)需要使用人工創(chuàng)建并拋出

// 手動拋出異常

public class Throw {
    public static void main(String[] args) {
        try{
            Student s = new Student();
            s.getID(-1001);
            System.out.println(s.toString());
        }catch(Exception e){
            System.out.println(e.getMessage());
            e.printStackTrace();
        }
    }
}

class Student{
    private int ID;
    
    public void getID(int ID) throws Exception{
        if(ID >= 0)
            this.ID = ID;
        else
//          System.out.println("輸入的值非法绣夺!");
//          throw new RuntimeException("輸入的值非法!");
            throw new Exception("輸入的值非法欢揖!");
    }

    @Override
    public String toString() {
        return "Student [ID=" + ID + "]";
    }
}

【子類重寫的方法】拋出的異常類型不能大于【父類被重寫的方法】拋出的異常類型

public class OverrideTest { 
    public static void main(String[] args) {
        OverrideTest test = new OverrideTest();
        test.display(new SubClass());
    }
    
    public void display(SuperClass s){
        try {
            s.method();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

class SuperClass{
    public void method() throws IOException{  };
}

class SubClass extends SuperClass{
    public void method() throws FileNotFoundException{  };
}

自定義異常

用戶自定義異常類MyException陶耍,用于描述數(shù)據(jù)取值范圍錯(cuò)誤信息。用戶自己的異常類必須繼承現(xiàn)有的異常類她混。

  • 一般地烈钞,用戶自定義異常類都是RuntimeException的子類。
  • 自定義異常類通常需要編寫幾個(gè)重載的構(gòu)造器坤按。
  • 自定義異常需要提供serialVersionUID
  • 自定義的異常通過throw拋出毯欣。
  • 自定義異常最重要的是異常類的名字,當(dāng)異常出現(xiàn)時(shí)臭脓,可以根據(jù)名字判斷異常類型酗钞。
public class MyException extends RuntimeException{
    
    static final long serialVersionUID = -317519865L;
    
    public MyException(){
        
    }
    
    public MyException(String msg){
        super(msg);
    }

}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市来累,隨后出現(xiàn)的幾起案子砚作,更是在濱河造成了極大的恐慌,老刑警劉巖嘹锁,帶你破解...
    沈念sama閱讀 218,546評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件葫录,死亡現(xiàn)場離奇詭異,居然都是意外死亡兼耀,警方通過查閱死者的電腦和手機(jī)压昼,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評論 3 395
  • 文/潘曉璐 我一進(jìn)店門求冷,熙熙樓的掌柜王于貴愁眉苦臉地迎上來瘤运,“玉大人,你說我怎么就攤上這事匠题≌兀” “怎么了?”我有些...
    開封第一講書人閱讀 164,911評論 0 354
  • 文/不壞的土叔 我叫張陵韭山,是天一觀的道長郁季。 經(jīng)常有香客問我,道長钱磅,這世上最難降的妖魔是什么梦裂? 我笑而不...
    開封第一講書人閱讀 58,737評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮盖淡,結(jié)果婚禮上年柠,老公的妹妹穿的比我還像新娘。我一直安慰自己褪迟,他們只是感情好冗恨,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,753評論 6 392
  • 文/花漫 我一把揭開白布答憔。 她就那樣靜靜地躺著,像睡著了一般掀抹。 火紅的嫁衣襯著肌膚如雪虐拓。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,598評論 1 305
  • 那天傲武,我揣著相機(jī)與錄音蓉驹,去河邊找鬼。 笑死揪利,一個(gè)胖子當(dāng)著我的面吹牛戒幔,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播土童,決...
    沈念sama閱讀 40,338評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼诗茎,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了献汗?” 一聲冷哼從身側(cè)響起敢订,我...
    開封第一講書人閱讀 39,249評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎罢吃,沒想到半個(gè)月后楚午,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,696評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡尿招,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,888評論 3 336
  • 正文 我和宋清朗相戀三年矾柜,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片就谜。...
    茶點(diǎn)故事閱讀 40,013評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡怪蔑,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出丧荐,到底是詐尸還是另有隱情缆瓣,我是刑警寧澤,帶...
    沈念sama閱讀 35,731評論 5 346
  • 正文 年R本政府宣布虹统,位于F島的核電站弓坞,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏车荔。R本人自食惡果不足惜渡冻,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,348評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望忧便。 院中可真熱鬧族吻,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,929評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至握础,卻和暖如春辐董,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背禀综。 一陣腳步聲響...
    開封第一講書人閱讀 33,048評論 1 270
  • 我被黑心中介騙來泰國打工简烘, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人定枷。 一個(gè)月前我還...
    沈念sama閱讀 48,203評論 3 370
  • 正文 我出身青樓孤澎,卻偏偏與公主長得像,于是被迫代替她去往敵國和親欠窒。 傳聞我的和親對象是個(gè)殘疾皇子覆旭,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,960評論 2 355

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