異常的捕獲及處理

異常:異常是指中斷程序正常執行的一種指令流
       JAVA程序中一旦出現了異常,而程序又沒有及時處理的情況下,那麼程序會中斷執行。
例如,觀察以下的代碼:
public class Demo22{

         public static void main(String args[]){

                   int i = 10 ;

                   int j = 0 ;

                   System.out.println(" --------- 計算開始 ---------") ;

                   System.out.println("i / j = " + (i / j)) ;   à 此段代碼出現了異常

                   System.out.println(" --------- 計算結束 ---------") ;

         }

};

       以上代碼編譯的時候不存在任何的問題,那麼執行時,出錯了,打印內容如下:
--------- 計算開始 ---------

Exception in thread "main" java.lang.ArithmeticException: / by zero

        at Demo22.main(Demo22.java:6)

       整個程序,在出現異常的代碼之後不再被執行了,異常之前的程序呢?正確的執行了。
       那麼在JAVA中我們所處理的異常都屬於運行時異常,即:執行JAVA程序的時候出現的錯誤,那麼實際上對於JAVA的異常分類應該按如下的形式劃分:
       ArithmeticException à RuntimeException à Exception(往往是要由用戶自己處理的)
       所以對於異常而言,它是一個統稱,代表了:
       Throwable(可能的拋出)

|- Exception:表示需要人爲處理的異常,指的是程序的錯誤 à 因爲程序的錯誤較多,所以就習慣了把所有的錯誤都統一成爲異常。
              |- Error:表示JVM錯誤,人爲不能處理
異常的處理格式如下:

try{

       包含可能出現錯誤的代碼段 ;

}catch(出錯的類型 出錯的對象){

       對於錯誤的處理語句 ;

}

       那麼使用如上的格式修改之前的代碼,保證程序可以正確的執行完:
public class Demo23{

         public static void main(String args[]){

                   int i = 10 ;

                   int j = 0 ;

                   System.out.println(" --------- 計算開始 ---------") ;

                   try{

                            System.out.println("i / j = " + (i / j)) ;

                   }catch(ArithmeticException e){

                            System.out.println("計算出現了錯誤。。。") ;

                   }

                   System.out.println(" --------- 計算結束 ---------") ;

         }

};

       但是以上的程序依然存在了些小小的問題,例如:對於計算,往往應該由用戶自己輸入數據,所以此時可以通過接收參數爲其輸入數據。代碼如下:
public class Demo24{

         public static void main(String args[]){

                   int i = 10 ;

                   int j = 0 ;

                   System.out.println(" --------- 計算開始 ---------") ;

                   try{

                            i = Integer.parseInt(args[0]) ;

                            j = Integer.parseInt(args[1]) ;

                            System.out.println("i / j = " + (i / j)) ;

                   }catch(ArithmeticException e){

                            System.out.println("計算出現了錯誤。。。") ;

                   }

                   System.out.println(" --------- 計算結束 ---------") ;

         }

};

       如果現在輸入的內容是正確的數字,則程序不會有任何的問題,但是既然數據是由用戶自己輸入的,那麼肯定會輸入各種違法的數據。
       存在的問題:
              · 不輸入任何參數,出現數組越界:ArrayIndexOutOfBoundsException
              · 輸入的參數不是數字,出現了數字格式轉換錯誤:NumberFormatException
              · 輸入的被除數是0,出現算術錯誤:ArithmeticException
       在以上的錯誤之中,只有算術錯誤被處理了,因爲在程序上具備了算術錯誤的處理能力。那麼也就意味着,現在的異常處理並不完善,需要加入更多的處理,所以需要編寫更多的catch
       以上的程序修改爲:
public class Demo24{

         public static void main(String args[]){

                   int i = 10 ;

                   int j = 0 ;

                   System.out.println(" --------- 計算開始 ---------") ;

                   try{

                            i = Integer.parseInt(args[0]) ;

                            j = Integer.parseInt(args[1]) ;

                            System.out.println("i / j = " + (i / j)) ;

                   }catch(ArithmeticException e){

                            System.out.println("算術錯誤。。。"+e) ;

                   }

                   catch(ArrayIndexOutOfBoundsException e){

                            System.out.println("沒有輸入參數。。。"+e) ;

                   }

                   catch(NumberFormatException e){

                            System.out.println("輸入的內容不是數字。。。"+e) ;

                   }

                   System.out.println(" --------- 計算結束 ---------") ;

         }

};

       但是會發現比較麻煩,因爲現在已經知道了的是三個錯誤,那麼對於很多未知道的錯誤呢?那麼此時,就需要分析異常的產生過程。
       發現catch中接收的內容都是對象,那麼也就意味着,所謂的異常,就是自動產生了一個異常類的實例化對象。一出錯就產生。
       對象有一個特點,可以向上自動轉型,Exception是用戶需要處理的最大異常,那麼證明所有的對象都可以向Exception轉換。
public class Demo25{

         public static void main(String args[]){

                   int i = 10 ;

                   int j = 0 ;

                   System.out.println(" --------- 計算開始 ---------") ;

                   try{

                            i = Integer.parseInt(args[0]) ;

                            j = Integer.parseInt(args[1]) ;

                            System.out.println("i / j = " + (i / j)) ;

                   }catch(ArithmeticException e){

                            System.out.println("算術錯誤。。。"+e) ;

                   }

                   catch(ArrayIndexOutOfBoundsException e){

                            System.out.println("沒有輸入參數。。。"+e) ;

                   }

                   catch(NumberFormatException e){

                            System.out.println("輸入的內容不是數字。。。"+e) ;

                   }

                   catch(Exception e){

                            System.out.println("其他異常。。。"+e) ;

                   }

                   System.out.println(" --------- 計算結束 ---------") ;

         }

};

注意:

       如果在程序中出現了多個catch語句,則捕獲更粗的catch要放在捕獲更細的catch之後。
public class Demo25{

         public static void main(String args[]){

                   int i = 10 ;

                   int j = 0 ;

                   System.out.println(" --------- 計算開始 ---------") ;

                   try{

                            i = Integer.parseInt(args[0]) ;

                            j = Integer.parseInt(args[1]) ;

                            System.out.println("i / j = " + (i / j)) ;

                   }catch(Exception e){

                            System.out.println("其他異常。。。"+e) ;

                   }catch(ArithmeticException e){

                            System.out.println("算術錯誤。。。"+e) ;

                   }catch(ArrayIndexOutOfBoundsException e){

                            System.out.println("沒有輸入參數。。。"+e) ;

                   }catch(NumberFormatException e){

                            System.out.println("輸入的內容不是數字。。。"+e) ;

                   }

                   System.out.println(" --------- 計算結束 ---------") ;

         }

};

       則編譯的時候出現了以下的錯誤,說是許多的異常已經被捕獲了。
Demo25.java:14: 已捕捉到異常 java.lang.ArithmeticException

                catch(ArithmeticException e){

                ^

Demo25.java:17: 已捕捉到異常 java.lang.ArrayIndexOutOfBoundsException

                catch(ArrayIndexOutOfBoundsException e){

                ^

Demo25.java:20: 已捕捉到異常 java.lang.NumberFormatException

                catch(NumberFormatException e){

                ^

3 錯誤

       既然所有異常類的對象都可以向Exception轉換,那麼是不是直接使用Exception接收更方便?
public class Demo26{

         public static void main(String args[]){

                   int i = 10 ;

                   int j = 0 ;

                   System.out.println(" --------- 計算開始 ---------") ;

                   try{

                            i = Integer.parseInt(args[0]) ;

                            j = Integer.parseInt(args[1]) ;

                            System.out.println("i / j = " + (i / j)) ;

                            System.out.println("***************************") ;

                   }catch(Exception e){

                            System.out.println(e) ;

                   }

                   System.out.println(" --------- 計算結束 ---------") ;

         }

};

       以上是異常處理的一種格式,實際上異常處理還有另外一種格式,就是說,可以爲異常做一個統一的出口,不管是否發生了異常,都要執行此代碼:
try{

         包含可能出現錯誤的代碼段 ;

}catch(出錯的類型 出錯的對象){

         對於錯誤的處理語句 ;

}finally{

         不管是否出現異常,都執行此代碼 ;

}

       代碼如下:
public class Demo27{

         public static void main(String args[]){

                   int i = 10 ;

                   int j = 0 ;

                   System.out.println(" --------- 計算開始 ---------") ;

                   try{

                            i = Integer.parseInt(args[0]) ;

                            j = Integer.parseInt(args[1]) ;

                            System.out.println("i / j = " + (i / j)) ;

                   }catch(Exception e){

                            System.out.println(e) ;

                   }finally{   à 典型的程序出口

                            System.out.println("不管是否存在異常,此代碼都會被執行。。。") ;

                   }

                   System.out.println(" --------- 計算結束 ---------") ;

         }

};

在異常處理中還有兩個很重要的關鍵字
       · throws:在方法的聲明處使用,表示此方法不處理異常,而交給被調用處處理。
       · throw:表示人爲的拋出一個異常。
例如:定義一個數學類,裏面有一個除法
class Math{

         // 此代碼有可能發生問題,也有可能不發生問題

         // 一旦發生問題,找調用處,誰調用的此方法,誰去處理

         public int div(int i,int j) throws Exception{

                   return i / j ;

         }

};

public class Demo28{

         public static void main(String args[]){

                   Math m = new Math() ;

                   System.out.println(m.div(10,2)) ;

         }

};

       按規定來說,此方法在調用的時候使用異常的捕獲,如果不使用,則編譯時出現以下的錯誤提示:
Demo28.java:11: 未報告的異常 java.lang.Exception;必須對其進行捕捉或聲明以便拋出

                System.out.println(m.div(10,2)) ;

                                        ^

1 錯誤

       所以對於調用有throws聲明的方法,必須使用try…catch
class Math{

         // 此代碼有可能發生問題,也有可能不發生問題

         // 一旦發生問題,找調用處,誰調用的此方法,誰去處理

         public int div(int i,int j) throws Exception{

                   return i / j ;

         }

};

public class Demo28{

         public static void main(String args[]){

                   Math m = new Math() ;

                   try{

                            System.out.println(m.div(10,0)) ;

                   }catch(Exception e){

                            System.out.println(e) ;

                   }

         }

};

       問?既然main方法是一個方法,那麼能不能在主方法上編寫throws語句呢?肯定是可以的
class Math{

         // 此代碼有可能發生問題,也有可能不發生問題

         // 一旦發生問題,找調用處,誰調用的此方法,誰去處理

         public int div(int i,int j) throws Exception{

                   return i / j ;

         }

};

public class Demo29{

         public static void main(String args[]) throws Exception{

                   Math m = new Math() ;

                   System.out.println(m.div(10,0)) ;

         }

};

       觀察錯誤的提示:
Exception in thread "main" java.lang.ArithmeticException: / by zero

        at Math.div(Demo29.java:5)

        at Demo29.main(Demo29.java:11)

       可以發現以上的錯誤提示與不使用try…catch效果是一樣的,證明所有的錯誤都交給了JVM進行處理,實際上在JAVA中默認的處理方式也就是使用JVM完成。
       throw:表示在程序中人爲的拋出一個異常,而且必須使用try…catch進行處理。
public class Demo30{

         public static void main(String args[]){

                   try{

                            throw new Exception("我自己樂意拋。。。") ;

                   }catch(Exception e){

                            System.out.println(e) ;

                   }

         }

};

       因爲對於異常而言,最終結果肯定都是拋出一個異常的實例化對象。所以是自己拋還是系統拋都肯定需要進行異常的捕獲及處理。
       設計一個除法操作,在操作之前編寫:計算開始,在操作之後編寫計算結束,中間不管是否出現了錯誤,都要打印這樣兩句話,問:該如何實現?
class Math{

         public int div(int i,int j) throws Exception{

                   System.out.println(" ======== 計算開始 =========") ;

                   int temp = 0 ;

                   try{

                            temp = i / j ;

                   }catch(Exception e){

                            throw e ;

                   }finally{

                            System.out.println(" ======== 計算結束 =========") ;

                   }

                   return temp ;

         }

};

public class Demo31{

         public static void main(String artgs[]){

                   Math m = new Math() ;

                  try{

                            System.out.println(m.div(1,0)) ;

                   }catch(Exception e){

                            System.out.println(e) ;

                   }

         }

};

       一般而言,對於throwthrowsfinally往往會一起使用。
自定義異常:

       一個類只要繼承了Exception就可以稱爲一個異常類。
class MyException extends Exception{

         public MyException(String msg){

                   super(msg) ;

         }

};

public class Demo32{

         public static void main(String args[]){

                   try{

                            throw new MyException("自己定義玩的。。") ;

                   }catch(Exception e){

                            System.out.println(e) ;

                   }

         }

};

注意點:

       · throwthrows的區別?
              |- throw:是人爲拋出異常
              |- throws:方法聲明處使用,表示在方法中不處理異常
       · finalfinally
              |- final:定義類、方法、常量
              |- finally:異常的統一出口
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章