1. 程式人生 > >04-異常處理-動手動腦

04-異常處理-動手動腦

1.請閱讀並執行AboutException.java示例,然後通過後面的幾頁PPT瞭解Java中實現異常處理的基礎知識。

import javax.swing.*;

class AboutException {
   public static void main(String[] a) 
   {
      int i=1, j=0, k;
      k=i/j;


    try
    {
        
        k = i/j;    // Causes division-by-zero exception
        //throw new Exception("Hello.Exception!");
} catch ( ArithmeticException e) { System.out.println("被0除. "+ e.getMessage()); } catch (Exception e) { if (e instanceof ArithmeticException) System.out.println("被0除"); else { System.out.println(e.getMessage()); } }
finally { JOptionPane.showConfirmDialog(null,"OK"); } } }

其輸出以下結果:

Exception in thread "main" java.lang.ArithmeticException: / by zero
at ketangceshi.AboutException.main(AboutException.java:9)

有關異常處理的知識:

處理機制:吧可能發生錯誤的程式碼放入try語句塊中,當程式檢測到出現了一個錯誤時會丟擲一個異常物件。異常處理程式碼會捕獲並處理這個錯誤(catch語句塊中的程式碼用於處理錯誤)。當異常發生時,程式控制流程由try語句塊跳轉到catch語句塊。不管是否有異常發生,finally語句塊中的語句始終保持被執行。如果沒有提供合適的異常處理程式碼,JVM將會結束掉整個應用程式。

異常分類:Throwable類有兩個直接子類: Exception:出現的問題是可以被捕獲的; Error:系統錯誤,通常由JVM處理。 可捕獲的異常又可以分為兩類: (1)Check異常:直接派生自Exception的異常類,必須被捕獲或再次宣告丟擲 (2)Runtime異常:派生自RuntimeException的異常類。使用throw語句可以隨時丟擲這種異常物件: throw new ArithmeticException(…);

上述情況出現的原因:異常處理有“多型”的特性。

異常多型特性

可以有多個catch語句塊,每個程式碼塊捕獲一種異常。在某個try塊後有兩個不同的catch 塊捕獲兩個相同型別的異常是語法錯誤。 使用catch語句,只能捕獲Exception類及其子類的物件。因此,一個捕獲Exception物件的catch語句塊可以捕獲所有“可捕獲”的異常。 將catch(Exception e)放在別的catch塊前面會使這些catch塊都不執行,因此Java不會編譯這個程式。

finally的功能

資源洩露:當一個資源不再被某應用程式使用,但此程式並未向系統宣告不再使用此資源時發生這種情況 finally語句塊主要用於解決資源洩露問題,它位於catch語句塊之後,JVM保證它們一定執行。 注意:finally語句塊中也可能發生異常,如果這種情況發生,先前的異常被放棄。

2.多層的異常捕獲-1

public class CatchWho { 
    public static void main(String[] args) { 
        try { 
                try { 
                    throw new ArrayIndexOutOfBoundsException(); 
                } 
                catch(ArrayIndexOutOfBoundsException e) { 
                       System.out.println(  "ArrayIndexOutOfBoundsException" +  "/內層try-catch"); 
                }
 
            throw new ArithmeticException(); 
        } 
        catch(ArithmeticException e) { 
            System.out.println("發生ArithmeticException"); 
        } 
        catch(ArrayIndexOutOfBoundsException e) { 
           System.out.println(  "ArrayIndexOutOfBoundsException" + "/外層try-catch"); 
        } 
    } 
}

執行結果如下:

3.多層的異常捕獲-2

public class CatchWho2 { 
    public static void main(String[] args) { 
        try {
                try { 
                    throw new ArrayIndexOutOfBoundsException(); 
                } 
                catch(ArithmeticException e) { 
                    System.out.println( "ArrayIndexOutOfBoundsException" + "/內層try-catch"); 
                }
            throw new ArithmeticException(); 
        } 
        catch(ArithmeticException e) { 
            System.out.println("發生ArithmeticException"); 
        } 
        catch(ArrayIndexOutOfBoundsException e) { 
            System.out.println( "ArrayIndexOutOfBoundsException" + "/外層try-catch"); 
        } 
    } 
}

執行結果如下:

 

4.動手動腦:當有多個巢狀的try...catch...finally時,要特別注意finally的執行時機。

public class EmbededFinally {

    
    public static void main(String args[]) {
        
        int result;
        
        try {
            
            System.out.println("in Level 1");

           
             try {
                
                System.out.println("in Level 2");
  // result=100/0;  //Level 2
               
                 try {
                   
                     System.out.println("in Level 3");
                      
                     result=100/0;  //Level 3
                
                } 
                
                catch (Exception e) {
                    
                    System.out.println("Level 3:" + e.getClass().toString());
                
                }
                
                
                finally {
                    
                    System.out.println("In Level 3 finally");
                
                }
                
               
                // result=100/0;  //Level 2

            
                }
            
            catch (Exception e) {
               
                 System.out.println("Level 2:" + e.getClass().toString());
           
             }
             finally {
                
                System.out.println("In Level 2 finally");
           
             }
             
            // result = 100 / 0;  //level 1
        
        } 
        
        catch (Exception e) {
            
            System.out.println("Level 1:" + e.getClass().toString());
        
        }
        
        finally {
           
.             System.out.println("In Level 1 finally");
        
        }
    
    }

}

執行結果如下:

當有多層巢狀的finally時,異常在不同的層次丟擲,在不同的位置丟擲,可能會導致不同的finally語句塊執行順序。

5.finally語句塊一定會執行嗎?

public class SystemExitAndFinally {

    
    public static void main(String[] args)
    {
        
        try{

            
            System.out.println("in main");
            
            throw new Exception("Exception is thrown in main");

                    //System.exit(0);

        
        }
        
        catch(Exception e)

            {
            
            System.out.println(e.getMessage());
            
            System.exit(0);
        
        }
        
        finally
        
        {
            
            System.out.println("in finally");
        
        }
    
    }


}

執行結果如下:

由執行結果分析得,finally語句塊中得內容不一定會執行。

6.如何跟蹤異常的傳播路徑?

// UsingExceptions.java
// Demonstrating the getMessage and printStackTrace
// methods inherited into all exception classes.
public class PrintExceptionStack {
   public static void main( String args[] )
   {
      try {
         method1();
      }
      catch ( Exception e ) {
         System.err.println( e.getMessage() + "\n" );
         e.printStackTrace();
      }
   }

   public static void method1() throws Exception
   {
      method2();
   }

   public static void method2() throws Exception
   {
      method3();
   }

   public static void method3() throws Exception
   {
      throw new Exception( "Exception thrown in method3" );
   }
}

執行結果如下:

當程式中出現異常時,JVM會依據方法呼叫順序依次查詢有關的錯誤處理程式。 可使用printStackTrace 和 getMessage方法瞭解異常發生的情況: printStackTrace:列印方法呼叫堆疊。 每個Throwable類的物件都有一個getMessage方法,它返回一個字串,這個字串是在Exception建構函式中傳入的,通常讓這一字串包含特定異常的相關資訊。