JavaSE學習筆記(6)---異常

JavaSE學習筆記(6)---異常

​ 軟件程序在運行過程當中,很是可能遇到問題,咱們稱之爲異常,英文是:Exception,意思是例外。遇到這些例外狀況,或者叫異常,咱們怎麼讓寫的程序作出合理的處理,安全的退出,而不至於程序崩潰呢?java

1.異常產生的緣由及使用原則

在 Java 中一個異常的產生,主要有以下三種緣由:數據庫

  1. Java 內部錯誤發生異常,Java 虛擬機產生的異常。
  2. 編寫的程序代碼中的錯誤所產生的異常,例如空指針異常、數組越界異常等。這種異常稱爲未檢査的異常,通常須要在某些類中集中處理這些異常。
  3. 經過 throw 語句手動生成的異常,這種異常稱爲檢査的異常,通常用來告知該方法的調用者一些必要的信息。

Java 經過面向對象的方法來處理異常。在一個方法的運行過程當中,若是發生了異常,則這個方法會產生表明該異常的一個對象,並把它交給運行時的系統,運行時系統尋找相應的代碼來處理這一異常。數組

咱們把生成異常對象,並把它提交給運行時系統的過程稱爲拋出(throw)異常。運行時系統在方法的調用棧中查找,直到找到可以處理該類型異常的對象,這一個過程稱爲捕獲(catch)異常安全

Java 異常強制用戶考慮程序的強健性和安全性。異常處理不該用來控制程序的正常流程,其主要做用是捕獲程序在運行時發生的異常並進行相應處理。編寫代碼處理某個方法可能出現的異常,可遵循以下三個原則:學習

  1. 在當前方法聲明中使用 try catch 語句捕獲異常。
  2. 一個方法被覆蓋時,覆蓋它的方法必須拋出相同的異常或異常的子類。
  3. 若是父類拋出多個異常,則覆蓋方法必須拋出那些異常的一個子集,而不能拋出新異常。

2.異常的類型

在 Java 中全部異常類型都是內置類 java.lang.Throwable 類的子類,即 Throwable 位於異常類層次結構的頂層。Throwable 類下有兩個異常分支 ExceptionError,如圖所示。測試

img

Throwable 類是全部異常和錯誤的父類,下面有 Error 和 Exception 兩個子類分別表示錯誤和異常。其中異常類 Exception 又分爲運行時異常和非運行時異常,這兩種異常有很大的區別,也稱爲不檢查異常(Unchecked Exception)和檢查異常(Checked Exception)。this

  • Exception 類用於用戶程序可能出現的異常狀況,它也是用來建立自定義異常類型類的類。
  • Error 定義了在一般環境下不但願被程序捕獲的異常。Error 類型的異經常使用於 Java 運行時由系統顯示與運行時系統自己有關的錯誤。堆棧溢出是這種錯誤的一例。
  • 本章不討論關於 Error 類型的異常處理,由於它們一般是災難性的致命錯誤,不是程序能夠控制的。本章接下來的內容將討論 Exception 類型的異常處理。

運行時異常都是 RuntimeException 類及其子類異常,如 NullPointerException、IndexOutOfBoundsException 等,這些異常是不檢查異常,程序中能夠選擇捕獲處理,也能夠不處理。這些異常通常由程序邏輯錯誤引發,程序應該從邏輯角度儘量避免這類異常的發生。線程

非運行時異常是指 RuntimeException 之外的異常,類型上都屬於 Exception 類及其子類。從程序語法角度講是必須進行處理的異常,若是不處理,程序就不能編譯經過。如 IOException、ClassNotFoundException 等以及用戶自定義的 Exception 異常,通常狀況下不自定義檢查異常。下表中列出了一些常見的異常類型及它們的做用。指針

異常類型 說明
Exception 異常層次結構的根類
RuntimeException 運行時異常,多數 java.lang 異常的根類
ArithmeticException 算術譜誤異常,如以零作除數
ArraylndexOutOfBoundException 數組大小小於或大於實際的數組大小
NullPointerException 嘗試訪問 null 對象成員,空指針異常
ClassNotFoundException 不能加載所需的類
NumberF ormatException 數字轉化格式異常,好比字符串到 float 型數字的轉換無效
IOException I/O 異常的根類
F ileN otF oundException 找不到文件
EOFException 文件結束
InterruptedException 線程中斷
IllegalArgumentException 方法接收到非法參數
ClassCastException 類型轉換異常
SQLException 操做數據庫異常

3.異常的處理

1.捕獲異常

捕獲異常是經過3個關鍵詞來實現的:try-catch-finally。用try來執行一段程序,若是出現異常,系統拋出一個異常,能夠經過它的類型來捕捉(catch)並處理它,最後一步是經過finally語句爲異常處理提供一個統一的出口,finally所指定的代碼都要被執行(catch語句可有多條;finally語句最多隻能有一條,根據本身的須要無關緊要)。如圖所示。code

圖6-10 異常處理.png

上面過程詳細解析:

1. try:

try語句指定了一段代碼,該段代碼就是異常捕獲並處理的範圍。在執行過程當中,當任意一條語句產生異常時,就會跳過該條語句中後面的代碼。代碼中可能會產生並拋出一種或幾種類型的異常對象,它後面的catch語句要分別對這些異常作相應的處理。

一個try語句必須帶有至少一個catch語句塊或一個finally語句塊 。

注意事項

當異常處理的代碼執行結束之後,不會回到try語句去執行還沒有執行的代碼。

2. catch:

n-每一個try語句塊能夠伴隨一個或多個catch語句,用於處理可能產生的不一樣類型的異常對象。

n-經常使用方法,這些方法均繼承自Throwable類 。

​ u-toString ()方法,顯示異常的類名和產生異常的緣由

​ u-getMessage()方法,只顯示產生異常的緣由,但不顯示類名。

​ u-printStackTrace()方法,用來跟蹤異常事件發生時堆棧的內容。

n-catch捕獲異常時的捕獲順序:

​ u-若是異常類之間有繼承關係,在順序安排上需注意。越是頂層的類,越放在下面,再否則就直接把多餘的catch省略掉。 也就是先捕獲子類異常再捕獲父類異常。

2. finally:

n-有些語句,不論是否發生了異常,都必需要執行,那麼就能夠把這樣的語句放到finally語句塊中。

n-一般在finally中關閉程序塊已打開的資源,好比:關閉文件流、釋放數據庫鏈接等。

try-catch-finally語句塊的執行過程:

try-catch-finally程序塊的執行流程以及執行結果比較複雜。

基本執行過程以下:

程序首先執行可能發生異常的try語句塊。若是try語句沒有出現異常則執行完後跳至finally語句塊執行;若是try語句出現異常,則中斷執行並根據發生的異常類型跳至相應的catch語句塊執行處理。catch語句塊能夠有多個,分別捕獲不一樣類型的異常。catch語句塊執行完後程序會繼續執行finally語句塊。finally語句是可選的,若是有的話,則不論是否發生異常,finally語句都會被執行。

注意事項

  1. 即便try和catch塊中存在return語句,finally語句也會執行。是在執行完finally語句後再經過return退出
  2. finally語句塊只有一種狀況是不會執行的,那就是在執行finally以前遇到了System.exit(0)結束程序運行

典型代碼

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class Test8 {
    public static void main(String[] args) {
        FileReader reader = null;
        try {
            reader = new FileReader("d:/a.txt");
            char c = (char) reader.read();
            char c2 = (char) reader.read();
            System.out.println("" + c + c2);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (reader != null) {
                    reader.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

2.拋出異常

當CheckedException產生時,不必定馬上處理它,能夠再把異常throws出去。

在方法中使用try-catch-finally是由這個方法來處理異常。可是在一些狀況下,當前方法並不須要處理髮生的異常,而是向上傳遞給調用它的方法處理。

若是一個方法中可能產生某種異常,可是並不能肯定如何處理這種異常,則應根據異常規範在方法的首部聲明該方法可能拋出的異常。

若是一個方法拋出多個已檢查異常,就必須在方法的首部列出全部的異常,之間以逗號隔開。

注意事項

方法重寫中聲明異常原則:子類重寫父類方法時,若是父類方法有聲明異常,那麼子類聲明的異常範圍不能超過父類聲明的範圍。

典型代碼

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
 
public class Test9 {
    public static void main(String[] args) {
        try {
            readFile("joke.txt");
        } catch (FileNotFoundException e) {
            System.out.println("所需文件不存在!");
        } catch (IOException e) {
            System.out.println("文件讀寫錯誤!");
        }
    }  
    public static void readFile(String fileName) throws FileNotFoundException,          
    IOException {
        FileReader in = new FileReader(fileName);
        int tem = 0;
        try {
            tem = in.read();
            while (tem != -1) {
                System.out.print((char) tem);
                tem = in.read();
            }
        } finally {
            in.close();
        }
    }
}

4.自定義異常

  1. 在程序中,可能會遇到JDK提供的任何標準異常類都沒法充分描述清楚咱們想要表達的問題,這種狀況下能夠建立本身的異常類,即自定義異常類。

  2. 自定義異常類只需從Exception類或者它的子類派生一個子類便可。

  3. 自定義異常類若是繼承Exception類,則爲受檢查異常,必須對其進行處理;若是不想處理,可讓自定義異常類繼承運行時異常RuntimeException類。

  4. 習慣上,自定義異常類應該包含2個構造器:一個是默認的構造器,另外一個是帶有詳細信息的構造器。

示例

自定義異常:

/**IllegalAgeException:非法年齡異常,繼承Exception類*/
class IllegalAgeException extends Exception {
    //默認構造器
    public IllegalAgeException() {
     
    }
    //帶有詳細信息的構造器,信息存儲在message中
    public IllegalAgeException(String message) {
        super(message);
    }
}

自定義異常的使用:

class Person {
    private String name;
    private int age;
 
    public void setName(String name) {
        this.name = name;
    }
 
    public void setAge(int age) throws IllegalAgeException {
        if (age < 0) {
            throw new IllegalAgeException("人的年齡不該該爲負數");
        }
        this.age = age;
    }
 
    public String toString() {
        return "name is " + name + " and age is " + age;
    }
}
 
public class TestMyException {
    public static void main(String[] args) {
        Person p = new Person();
        try {
            p.setName("Lincoln");
            p.setAge(-1);
        } catch (IllegalAgeException e) {
            e.printStackTrace();
            System.exit(-1);
        }
        System.out.println(p);
    }
}

執行結果:

圖6-11 示例6-11運行效果圖.png

5.使用異常機制的建議

1.要避免使用異常處理代替錯誤處理,這樣會下降程序的清晰性,而且效率低下。

2.處理異常不能夠代替簡單測試---只在異常狀況下使用異常機制。

3.不要進行小粒度的異常處理---應該將整個任務包裝在一個try語句塊中。

4.異常每每在高層處理(先了解!後面作項目會說!) 。

相關文章
相關標籤/搜索