歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

Java基礎知識學習:異常

  當異常發生時,原本要接著執行的代碼不再執行,轉而讓其他部分的代碼來處理。如果沒有代碼負責處理,控制台會報告異常。

  異常出現時的執行機制

 

  異常機制最大的好處是:清晰地分開了 正常的業務邏輯遇到情況時的處理 代碼。(當在業務邏輯中,有多步可能會拋出不同的異常時,異常處理機制的好處更得以體現。如果沒有這種機制,也許會通過很多的if...else...來實現異常處理,甚至是多層嵌套的if...else...,這樣的代碼可讀性很差)

  通過例子來理解:

package exception;

public class ExceptionCatch {
   public static void main(String[] args) {
     try {
       //我們通過拋出異常來抽象真實的業務邏輯,可能某一步會出現異常,這時下面的代碼就不再執行,轉而到處理代碼。
       //執行完處理代碼之後不會再回到之前try裡沒執行完的代碼繼續執行,而是去往下執行try{}catch{}之後的代碼。 throw new NullPointerException();
            throw new ArrayIndexOutOfBoundsException();
       throw ...                  
}catch(NullPointerException e) {     //異常處理代碼 }catch(ArrayIndexOutOfBoundsException e) {
       //異常處理代碼
     }catch(Exception e){
       //異常處理代碼
 } } }

   -----------------------------------------------------

  捕捉到異常之後怎麼處理?

  當catch到一場之後,根據你的業務邏輯來對它進行處理,比如說可以彈出一個窗口來警告用戶發生了錯誤,或者讓程序自己重新執行或者終止掉等等。當然,如果現在處理不了這個異常,也可以將它再次拋出。

  處理完異常之後是回不到異常發生的地方繼續執行一下的代碼了,而是從catch{}後面的代碼開始執行。

  一個異常只能被捕捉一次,捕捉之後這個異常就沒有了。不可能再次捕捉到。

   -----------------------------------------------------

  自定義異常類的構造器getMessage()方法的使用 :

 1 package exception;
 2 
 3 //注意觀察兩個異常類構造器的區別。

  /**
   * 推斷:
   * 第一個異常類是自己定義了一個String變量,在構造的時候是將信息傳給了這個變量;
   * 而第二個異常類的構造器是覆蓋了父類的構造方法,所以我們猜測,父類Exception裡一定有一個String類型的成員變量(這個成員變量同樣繼承給了MyException子類),
   * 所以在構造的時候利用super()將父類的構造方法取過來,進而將信息傳給了父類裡的那個String成員變量。
   * 而getMessage()方法也是從父類那裡繼承來的,進而我們推斷:getMessage()方法返回的正是那個String變量。
   * 在第一個異常類的那個從父類繼承的String變量並沒有被賦值,所以通過getMessage()取到的是null。
   */
 4 class MyException extends Exception {
 5     String msg;
 6     public MyException(String msg) {
 7         this.msg = msg;
 8     }
 9     public void printMsg() {
10         System.out.println("msg = " + msg);
11     }
12 }
13 
14 class MyException2 extends Exception {
15     public MyException2(String s) { 
16         super(s); 
17     }
18 }
19 
20 public class E04_ExceptionClass {
21     public static void main(String args[]) {
22         try {
23             throw new MyException("MyException message");
24         } catch(MyException e) {
25             e.printMsg();
26             System.out.println("e.getMessage() = " + e.getMessage()); //輸出為null。
27         }
28         
29         try {
30             throw new MyException2("MyException2 message");
31         } catch(MyException2 e) {
32             System.out.println("e.getMessage() = " + e.getMessage());
33         }
34     }
35 }
36 /*Output:msg = MyException message
37  *       e.getMessage() = null
38  *       e.getMessage() = MyException2 message
39  */

   -----------------------------------------------------

  printStackTrace()方法:堆棧跟蹤

  我們知道在程序代碼執行的過程中,某個主線程可能會調用其他的代碼程序,調用執行之後,回來繼續執行主線程。這個過程中就需要堆棧來存儲調用時的斷點。(因為在嵌套調用的時候會需要存儲多個斷點,返回的時候再倒序依次返回,這要遵循後進先出的原則。)

  堆棧跟蹤便可以看成是對代碼調用的跟蹤,當異常發生時可以根據該異常的printStackTrace()方法,打印出該異常的整個傳遞過程

  -----------------------------------------------------

  一個方法裡如果會拋出異常,則必須在其方法後面聲明 throws 異常名 。如果不聲明則必須在這個方法裡通過 try{}catch{} 將異常處理掉。

  一個方法可以聲明多個異常拋出 throws 異常1 , 異常2 ,但是在以後調用該方法時必須有多個catch來捕捉不同的異常。溫馨提示:往往在編程時,會把所有可能會有的異常(現在會有的和以後可能會有的)全都聲明在方法之後,這是一種習慣。因為在後期在對該方法進行功能擴展時可能會遇到出現這些異常,而當時在聲明這些異常之後編譯器會提示你將這些異常一一catch���所以這時你只需要填補catch裡的處理內容,這會來帶一定的便利。

  下面是一個示例:

package exception;

class OpenException extends Throwable {}
class CloseException extends Throwable {}

public class c {
    public static int open() {
        return -1;
    }
    
    public static void readFile() throws OpenException,CloseException {
        if(open() == -1) throw new OpenException();
    }
    
    public static void main(String[] args) {
        try {
            readFile();
        } catch (OpenException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (CloseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    
}

Copyright © Linux教程網 All Rights Reserved