Error錯誤,通常是指與虛擬機相關的問題,如系統崩潰、虛擬機錯誤、動態連接失敗等,這種錯誤沒法恢復或不可捕獲,將致使應用程序中斷。一般應用程序沒法處理這些錯誤,所以應用程序不該該試圖使用catch塊來捕獲Error對象。在定義該方法時,也無須在其throws子句中聲明該方法可能拋出Error及其任何子類。java
實際上,進行異常捕獲時不只應該把Exception類對應的catch塊放在最後,並且全部父類異常的catch塊都應該排在子類異常catch塊的後面(簡稱:先處理小異常,再處理大異常),不然將出現編譯錯誤。數據庫
有時候程序在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也能夠包含異常處理。對象
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
一般,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代碼在某處所拋出的異常。簡單地說,異常老是先被拋出,後被捕捉的。
當出現一個狀況時,單靠某個方法沒法徹底處理該異常,必須由幾個方法協做纔可徹底處理該異常。也就是說,在異常出現的當前方法中,程序只對異常進行部分處理,還有些處理須要在該方法的調用者中才能完成,因此應該再次拋出異常,讓該方法的調用者也能捕獲異常。
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()); } } }