異常處理(try...catch...final 和 throw , throws)


1.傳統(弱語言)處理異常方式

原理:利用判斷來控制異常出現

 

 1 publicclass Test01 {
 2     publicstaticvoid main(String[] args) {
 3         Scanner sc = new Scanner(System.in);
 4         System.out.println("請輸入第一個數:");
 5         
 6         intnum1 = 0;
 7         if(sc.hasNextInt()) {            
 8             num1 = sc.nextInt();
 9             
10             System.out.println("請輸入第二個數:");
11             intnum2 = 0;
12             if(sc.hasNextInt()) {
13                 num2 = sc.nextInt();
14                 
15                 if(0 == num2) {
16                     System.out.println("除數不能為0!");
17                 }else {                    
18                     intr = num1 / num2;
19                     System.out.println("num1/num2 = "+r);
20                 }
21 
22             }else {
23                 System.out.println("第二個數輸入不是數字");
24             }
25             
26         }else {
27             System.out.println("第一個數輸入不是數字!");
28         }
29     }
30 }

 

這樣做的缺點:

【1】通過判斷處理異常影響執行效率。

【2】判斷邏輯和業務邏輯交織在一起,不利於后期維護。

2.異常

異常是所有異常類的直接或間接父類。

異常是指在運行過程中發生了不正常的情況,這是它就會中斷程序。

異常處理機制:指java中異常處理機制為程序提供處理異常的能力,從而使程序不中斷的運行。

 

 3.異常處理

異常處理的關鍵字有:try...catch 和 try...catch...finally  

1)try...catch

解釋:try— 把有可能產生異常的代碼放到try代碼塊中,catch—負責捕獲異常並匹配異常再處理異常。

【1】正常執行,沒有遇到異常

【2】出現異常,異常處理,正常結束。(紅字是處理異常步驟)

異常常見方法:

prinStackTrace:打印異常的執行堆棧信息(在控制台中異常堆棧信息輸出位置不固定)

1 java.util.InputMismatchException
2     at java.util.Scanner.throwFor(Scanner.java:864)
3     at java.util.Scanner.next(Scanner.java:1485)
4     at java.util.Scanner.nextInt(Scanner.java:2117)
5     at java.util.Scanner.nextInt(Scanner.java:2076)
6     at cn.sxt02.exception02.Test01.main(Test01.java:14)

一般,異常的堆棧信息很多,開發者只需要看懂

 ——第一行:異常簡單的信息(異常類型,異常描述等)

——最后一行:異常出現的位置(如上的Test01.java:14)

getMessage:返回異常的描述信息

 1 packagecn.sxt02.exception02;
 2 importjava.util.Scanner;
 3 publicclass Test01 {
 4     publicstaticvoid main(String[] args) {
 5         Scanner sc = new Scanner(System.in);
 6         System.out.println("請輸入第一個數:");
 7 
 8         intnum1 = 0;
 9         intnum2 = 0;
10         
11         try {
12             num1 = sc.nextInt();
13 
14             System.out.println("請輸入第二個數:");
15             num2 = sc.nextInt();
16 
17             intr = num1 / num2;
18             System.out.println("num1/num2 = " + r);
19         }catch (Exception e) {
20             System.out.println("程序出現異常");
21             // 打印異常的信息
22             // System.out.println(e.toString());
23             
24             
25             // 打印異常堆棧信息
26             e.printStackTrace();
27             
28             // 返回異常的描述信息,如果沒有信息,返回null(InputMismatchException沒有描述信息)
29             System.out.println(e.getMessage());
30         }
31         
32         System.out.println("程序正常結束");
33     }

【3】異常類型不匹配

【4】多重catch

 1 publicclass Test03 {
 2     publicstaticvoid main(String[] args) {
 3         Scanner sc = new Scanner(System.in);
 4         System.out.println("請輸入第一個數:");
 5     
 6         intnum1 = 0;
 7         intnum2 = 0;
 8         
 9         try {
10             num1 = sc.nextInt();
11 
12             System.out.println("請輸入第二個數:");
13             num2 = sc.nextInt();
14 
15             intr = num1 / num2;
16             System.out.println("num1/num2 = " + r);
17         }catch (ArithmeticExceptione) {
18             System.out.println("數學計算異常:"+e.getMessage());
19         }catch(InputMismatchExceptione) {
20             System.out.println("輸入不匹配異常:"+e.getMessage());
21         }catch (Exception e) {
22             System.out.println("發送異常:"+e.getMessage());
23         }
24         
25         System.out.println("程序正常結束");
26     }
27 }

2)try...catch...finally  

 解讀:把有可能產生異常的代碼放到try的代碼塊中,catch捕捉異常並匹配異常再處理異常,finally塊用於收尾工作

(如關閉數據庫,關閉文件,釋放內存等資源)

注:finally :無論是否發生異常,finally都將執行,常用於收尾工作

 1 publicstaticvoid main(String[] args) {
 2         Scanner sc = new Scanner(System.in);
 3         System.out.println("請輸入第一個數:");
 4 
 5         intnum1 = 0;
 6         intnum2 = 0;
 7 
 8         try {
 9             num1 = sc.nextInt();
10 
11             System.out.println("請輸入第二個數:");
12             num2 = sc.nextInt();
13 
14             intr = num1 / num2;
15             System.out.println("num1/num2 = " + r);
16         } catch (Exception e) {
17             System.out.println("程序出現異常");
18         } finally {
19             System.out.println("不管是否出現異常,finally都執行");
20         }
21 
22         System.out.println("程序正常結束");
23     }

特殊情況:

【1】finally不執行的情況

System.exit(0)正常退出jvm,程序結束,不會執行finally

【2】catch可以省略,變成try...finally形式

4.return

當return存在於try...catch...finally時的執行順序(return始終在最后)

 

 1 packagecn.sxt02.exception03;
 2 
 3 /**
 4  * 存在return的情況
 5  */
 6 publicclass Test02 {
 7 
 8     publicstaticintdiv(inta, intb) {
 9 
10         try {
11             intr = a / b;
12             returnr;
13 
14         } catch (Exception e) {
15             System.out.println("出現異常");
16 
17             return 0;
18 
19         } finally {
20             System.out.println("我是finally");
21         }
22 
23     }
24 
25     publicstaticvoid main(String[] args) {
26 
27         intr = Test02.div(10, 0);
28         System.out.println("r=" + r);
29         System.out.println("程序正常結束");
30     }
31 }

 

5.異常的分類

Throwable類是 Java 語言中所有錯誤(Error)或異常(Exception)的父類,只有當對象是此類(或其子類之一)的實例時,才能通過 Java 虛擬機或者 Java throw 語句拋出。

Error 類表示錯誤類。僅靠程序本身無法恢復的嚴重錯誤。如jvm內存耗盡、jvm崩潰等。

Exception類表示異常類,可以通過java 異常處理機制處理。

Exception根據是否處理分為兩種情況。

RuntimeException:運行時異常。不要求程序必須做出處理。是所有運行時異常的父類。

CheckedException:檢查時異常。要求程序必須處理,不處理編譯不通過。

 1 publicclass Test01 {
 2     publicstaticvoid main(String[] args) {
 3         // 運行時異常
 4         Scanner sc = new Scanner(System.in);
 5         // runtime exception
 6         intr = sc.nextInt();
 7         System.out.println("r = "+ r);
 8         
 9         // 檢查時異常
10         SimpleDateFormatdf = newSimpleDateFormat();
11         try {
12             Date date = df.parse("2019");
13         } catch (ParseExceptione) {
14             e.printStackTrace();
15         }
16     }
17 }

常見的運行時異常

ArithmeticException:數學計算異常。如除數為0

InputMismatchException:輸入不匹配異常。

ArrayIndexOutofBoundsException:數組下標越界異常。

NullPointException:空指針異常,對象沒有初始化就使用時,jvm就會拋出該異常。

IllegalArgumentException:非法參數異常。

ClassCastException:強制類型轉化異常。

NumberFormatException:數字格式化異常。如把“abc”格式化為數字。

常見的檢查時異常:

ClassNotFoundException:類沒有被發現異常。

SQLException:數據庫相關異常
IOException:IO操作異常
ParseException:解析錯誤異常
FileNotFoundException:文件未發現異常。
運行時異常和檢查時異常的區別:

  運行時異常:包括RuntimeException及其所有子類。不要求程序必須對它們作出處理,比如InputMismatchException、                 ArithmeticException、NullPointerException等。即使沒有使用try-catch或throws進行處理,仍舊可以進行

        編譯和運行。如果運行時發生異常,會輸出異常的堆棧信息並中止程序執行。

  檢查時異常:Checked異常(非運行時異常):除了運行時異常外的其他異常類都是Checked異常。程序必須捕獲或者

        聲明拋出這種異常,否則出現編譯錯誤,無法通過編譯。處理方式包括兩種:通過try-catch捕獲異常,

        通過throws聲明拋出異常從而交給上一級調用方法處理

6.聲明異常

1)throws關鍵字

解讀:當一個方法可能存在異常,而此時自身又無法更好的處理,可以交給外界處理。此時用throws聲明並拋出異常。

 1 publicclass Test01 {
 2 
 3     publicstaticintdiv(inta, intb) throws ArithmeticException{
 4         intr = 0;
 5         r = a / b;
 6         returnr;
 7     }
 8 
 9     publicstaticvoid main(String[] args) {
10         try {
11             Test01.div(10, 0);
12         } catch (ArithmeticExceptione) {
13             System.out.println("除數不能為0");
14         }
15     }
16 }

  注:開發者可以根據需求聲明檢查時異常 (Exception或者非運行時異常及其子類)  和運行時異常(RuntimeException或其子類)

 如果拋出異常后,調用處不知道如何處理異常,可以選擇繼續聲明異常(拋出異常),這個過程叫做異常上拋。

 1 publicclass Test01 {
 2 
 3     publicstaticintdiv(inta, intb) throws Exception{
 4         intr = 0;
 5         r = a / b;
 6         returnr;
 7     }
 8 
 9     publicstaticvoid main(String[] args) throws Exception{
10         
11         //【1】調用處知道如何處理!
12         /*
13         try {
14             Test01.div(10, 0);
15         } catch (Exception e) {
16             e.printStackTrace();
17         }
18         */
19         
20         // 【2】調用處也不知道如何處理
21         Test01.div(10, 0);
22         
23     }
24 }

2)聲明異常和重載的關系

聲明異常和重載沒有任何關系

 1 publicclass Test01 {
 2 
 3     publicstaticintdiv(inta, intb) throws Exception{
 4         intr = 0;
 5         r = a / b;
 6         returnr;
 7     }
 8     
 9     publicstaticintdiv(inta, intb) {
10         intr = 0;
11         r = a / b;
12         returnr;
13     }
14 }

注:方法重載:

【1】方法名相同

【2】參數列表不同(個數,類型,不同類型的順序不同)

【3】和返回值,修飾符,聲明異常無關

 3)聲明異常和重寫的關系

聲明異常和方法重寫有關系,關系如下

[1]父類方法聲明了異常(檢測時或運行時),子類可以不聲明任何異常。

publicclass Father {

    publicvoidshowInfo() throws Exception{
        
    }
}
publicclass Son extendsFather{
    
    @Override
    publicvoidshowInfo(){
        
    }
    
}

理解:父類方法拋出異常,子類在重寫過程中把該異常處理掉了,所以子類方法不用聲明異常。

[2] 父類方法聲明沒有聲明任何異常(檢測時或運行時),子類也不聲明異常或者聲明運行時異常。

publicclass Father {

    publicvoidshowInfo(){
        
    }
}
publicclass Son extendsFather{
    
    @Override
    publicvoidshowInfo() throws Exception{
        
    }
    
}

[3]父類聲明了異常(檢測時或運行時),子類聲明完全一樣的異常。

publicclass Father {

    publicvoidshowInfo() throwsException{
        
    }
}
publicclass Son extendsFather{
    
    @Override
    publicvoidshowInfo() throwsException {
        
    }
    
}

7.手動拋出異常

1)throw

除了系統自動拋出異常外,有些問題需要開發者手動拋出異常。使用關鍵字throw

 1 packagecn.sxt02.exception06;
 2 
 3 publicclass Student {
 4     private String name;
 5     private String gender;
 6 
 7     public String getName() {
 8         returnname;
 9     }
10 
11     publicvoidsetName(String name) {
12         this.name = name;
13     }
14 
15     public String getGender() {
16         returngender;
17     }
18 
19     publicvoidsetGender(String gender) throws Exception{
20         if(gender.equals("男") || gender.equals("女")) {            
21             this.gender = gender;
22         }else {
23             thrownew Exception("性別不合法!");
24         }
25     }
26 
27     publicStudent(String name, String gender) {
28         super();
29         this.name = name;
30         this.gender = gender;
31     }
32 
33     publicStudent() {
34         super();
35     }
36     
37 }
 1 publicclass Test01 {
 2     publicstaticvoid main(String[] args){
 3         Student stu = newStudent();
 4         stu.setName("二狗");
 5         try {
 6             stu.setGender("xxx");
 7         } catch (Exception e) {
 8             System.out.println(e.getMessage());
 9         }
10     }
11 }

2)自定義異常

理解:如果開發者需要手動拋出的異常在系統不存在,可以自定義異常。

注意:如果要自定義異常,首先要確定異常類型,如果異常是運行時異常,必須繼承RuntimeException或其子類;如果異常是檢查時異常,必須繼承Exception或其子類。

     ——異常的命名方式,參考系統命名方式,以Exception結尾。

publicclassAgeExceptionextendsException{

    publicAgeException() {
        super();
    }

    publicAgeException(String message) {
        super(message);
    }
    
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM