異常處理

java類的繼承體系

  Error錯誤,通常是指與虛擬機相關的問題,如系統崩潰、虛擬機錯誤、動態連接失敗等,這種錯誤沒法恢復或不可捕獲,將致使應用程序中斷。一般應用程序沒法處理這些錯誤,所以應用程序不該該試圖使用catch塊來捕獲Error對象。在定義該方法時,也無須在其throws子句中聲明該方法可能拋出Error及其任何子類。java

  實際上,進行異常捕獲時不只應該把Exception類對應的catch塊放在最後,並且全部父類異常的catch塊都應該排在子類異常catch塊的後面(簡稱:先處理小異常,再處理大異常),不然將出現編譯錯誤。數據庫

使用finally回收資源

有時候程序在try塊中打開一些物理資源(例如數據庫鏈接、網絡鏈接和磁盤文件等)這些物理資源都必須顯示回收。java垃圾回收機制不會回收任何物理資源,垃圾回收機制只能回收堆內存中對象所佔用的內存。網絡

import java.io.*;
public class FinallyTest
{
    public static void main(String[] args)
    {
        FileInputStream fis = null;
        try
        {
            fis = new FileInputStream("b.txt");
        }
        catch (IOException ioe)
        {
            System.out.println(ioe.getMessage());
            // return語句強制方法返回
            return ;       //// 使用exit來退出虛擬機
            // System.exit(1);     //
        }
        finally
        {
            // 關閉磁盤文件,回收資源
            if (fis != null)
            {
                try
                {
                    fis.close();
                }
                catch (IOException ioe)
                {
                    ioe.printStackTrace();
                }
            }
            System.out.println("執行finally塊裏的資源回收!");
        }
    }
}

輸出:spa

b.txt (系統找不到指定的文件。)
執行finally塊裏的資源回收!

  雖然return語句也可強制方法結束,可是必定會先執行finally塊裏的代碼。若是把①註釋掉,取消②的註釋,那麼不會執行finally塊裏的代碼。也就是說,除非在try塊、catch塊中調用了退出虛擬機的方法,不然無論在try塊、catch塊中執行怎樣的代碼,出現怎樣的狀況,異常處理的finally塊總會被執行。指針

  一般狀況下,不要在finally塊中使用如return或throw等致使方法終止的語句,這將會致使try塊、catch塊中的return、throw語句失效。當java程序執行try塊、catch塊時遇到了return或throw語句,這兩個語句都會致使該方法當即結束,可是系統執行這兩個語句並不會結束該方法,而是去尋找該異常處理流程中是否包含finally塊,若是沒有finally快塊,程序當即執行return或throw語句,方法終止;若是有finally塊,程序當即開始執行finally塊——只有當finally塊執行完成後,系統纔會再次跳回來執行try塊、catch塊裏的return或throw語句,若是finally塊裏也使用了return或throw等致使方法終止的語句,finally已經終止了方法,系統將不會跳回去執行try塊、catch塊裏的任何代碼。code

  如上所示,finally也能夠包含異常處理。對象

自動關閉資源的try語句

import java.io.*;
public class AutoCloseTest {
    public static void main(String[] args) throws IOException {
        try (
                // 聲明、初始化兩個可關閉的資源
                // try語句會自動關閉這兩個資源。
                BufferedReader br = new BufferedReader(new FileReader("AutoCloseTest.java"));
                PrintStream ps = new PrintStream(new FileOutputStream("a.txt"))) {
            // 使用兩個資源
            System.out.println(br.readLine());
            ps.println("莊生曉夢迷蝴蝶");
        }
    }
}

java7加強了try語句的功能,它容許在try關鍵字後緊跟一對圓括號,圓括號能夠聲明、初始化一個或多個資源,此處的資源指的是那些必須在程序結束時顯式關閉的資源(好比數據庫鏈接、網絡鏈接),try語句在該語句結束時自動關閉這些資源。blog

 checked異常和unchecked異常

  一般,Java的異常(包括Exception和Error)分爲可查的異常(checked exceptions)和不可查的異常(unchecked exceptions)
  可查異常(編譯器要求必須處置的異常):正確的程序在運行中,很容易出現的、情理可容的異常情況。可查異常雖然是異常情況,但在必定程度上它的發生是能夠預計的,並且一旦發生這種異常情況,就必須採起某種方式進行處理。繼承

      除了RuntimeException及其子類之外,其餘的Exception類及其子類都屬於可查異常。這種異常的特色是Java編譯器會檢查它,也就是說,當程序中可能出現這類異常,要麼用try-catch語句捕獲它,要麼用throws子句聲明拋出它,不然編譯不會經過。內存

     不可查異常(編譯器不要求強制處置的異常):包括運行時異常(RuntimeException與其子類)和錯誤(Error)。

     Exception 這種異常分兩大類運行時異常和非運行時異常(編譯異常)。程序中應當儘量去處理這些異常。

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

      運行時異常的特色是Java編譯器不會檢查它,也就是說,當程序中可能出現這類異常,即便沒有用try-catch語句捕獲它,也沒有用throws子句聲明拋出它,也會編譯經過。
       非運行時異常 (編譯異常):是RuntimeException之外的異常,類型上都屬於Exception類及其子類。從程序語法角度講是必須進行處理的異常,若是不處理,程序就不能編譯經過。如IOException、SQLException等以及用戶自定義的Exception異常,通常狀況下不自定義檢查異常。

 因爲運行時異常的不可查性,爲了更合理、更容易地實現應用程序,Java規定,運行時異常將由Java運行時系統自動拋出,容許應用程序忽略運行時異常。

      對於方法運行中可能出現的Error,當運行方法不欲捕捉時,Java容許該方法不作任何拋出聲明。由於,大多數Error異常屬於永遠不能被容許發生的情況,也屬於合理的應用程序不應捕捉的異常。

      對於全部的可查異常,Java規定:一個方法必須捕捉,或者聲明拋出方法以外。也就是說,當一個方法選擇不捕捉可查異常時,它必須聲明將拋出異常。

  可以捕捉異常的方法,須要提供相符類型的異常處理器。所捕捉的異常,多是因爲自身語句所引起並拋出的異常,也多是由某個調用的方法或者Java運行時 系統等拋出的異常。也就是說,一個方法所能捕捉的異常,必定是Java代碼在某處所拋出的異常。簡單地說,異常老是先被拋出,後被捕捉的。

catch和throw同時使用

  當出現一個狀況時,單靠某個方法沒法徹底處理該異常,必須由幾個方法協做纔可徹底處理該異常。也就是說,在異常出現的當前方法中,程序只對異常進行部分處理,還有些處理須要在該方法的調用者中才能完成,因此應該再次拋出異常,讓該方法的調用者也能捕獲異常。

import exception.AuctionException;
public class AuctionTest
{
    private double initPrice = 30.0;
    // 由於該方法中顯式拋出了AuctionException異常,
    // 因此此處須要聲明拋出AuctionException異常
    public void bid(String bidPrice)
        throws AuctionException
    {
        double d = 0.0;
        try
        {
            d = Double.parseDouble(bidPrice);
        }
        catch (Exception e)
        {
            // 此處完成本方法中能夠對異常執行的修復處理,
            // 此處僅僅是在控制檯打印異常跟蹤棧信息。
            e.printStackTrace();
            // 再次拋出自定義異常
            throw new AuctionException("競拍價必須是數值,"
                + "不能包含其餘字符!");
        }
        if (initPrice > d)
        {
            throw new AuctionException("競拍價比起拍價低,"
                + "不容許競拍!");
        }
        initPrice = d;
    }
    public static void main(String[] args)
    {
        AuctionTest at = new AuctionTest();
        try
        {
            at.bid("df");
        }
        catch (AuctionException ae)
        {
            // 再次捕捉到bid方法中的異常。並對該異常進行處理
            System.err.println(ae.getMessage());
        }
    }
}
相關文章
相關標籤/搜索