異常指不期而至的各類情況,如:文件找不到、網絡鏈接失敗、非法參數等。異常是一個事件,它發生在程序編譯或運行期間,干擾了正常的指令流程。java
Java中的Throwable類是全部異常的基類。它的的衆多子類描述各類不一樣的異常。於是,Java異常都是對象,是Throwable子類的實例,描述了出如今一段編碼中的 錯誤條件。當條件生成時,錯誤將引起異常。面試
Throwable 類是 Java 語言中全部錯誤或異常的超類編程
注意:異常和錯誤的區別:異常能被程序自己能夠處理,錯誤是沒法處理。數組
1 Exception 類及其子類用來處理程序錯誤,它指出了合理的應用程序想要捕獲的條件,表示程序自己能夠處理的異常網絡
2 Error 是及其子類用來處理系統錯誤,表示僅靠程序自己沒法恢復的嚴重錯誤,用於指示合理的應用程序不該該試圖捕獲的嚴重問題,Java編譯器不去檢查這類異常框架
RuntimeException 類及其子類表示「JVM 經常使用操做」引起的錯誤。例如,若試圖使用空值對象引用、除數爲零或數組越界,則分別引起運行時異常(NullPointerException、ArithmeticException)和 ArrayIndexOutOfBoundException。編程語言
一般,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技術所要求的異常處理方式有所不一樣。
只有在try裏面是有System.exit(0)來退出JVM的狀況下finally塊中的代碼纔不會執行。
因爲運行時異常的不可查性,爲了更合理、更容易地實現應用程序,Java規定,運行時異常將由Java運行時系統自動拋出,容許應用程序忽略運行時異常。
對於方法運行中可能出現的Error,當運行方法不欲捕捉時,Java容許該方法不作任何拋出聲明。由於,大多數Error異常屬於永遠不能被容許發生的情況,也屬於合理的應用程序不應捕捉的異常。
對於全部的可查異常,Java規定:一個方法必須捕捉,或者聲明拋出方法以外。也就是說,當一個方法選擇不捕捉可查異常時,它必須聲明將拋出異常。
1) 若是是不可查異常(unchecked exception),即Error、RuntimeException或它們的子類,那麼能夠不使用throws關鍵字來聲明要拋出的異常,編譯仍能順利經過,但在運行時會被系統拋出。
2)必須聲明方法可拋出的任何可查異常(checked exception)。即若是一個方法可能出現受可查異常,要麼用try-catch語句捕獲,要麼用throws子句聲明將它拋出,不然會致使編譯錯誤
3)僅當拋出了異常,該方法的調用者才必須處理或者從新拋出該異常。當方法的調用者無力處理該異常的時候,應該繼續拋出,而不是囫圇吞棗。
4)調用方法必須遵循任何可查異常的處理和聲明規則。若覆蓋一個方法,則不能聲明與覆蓋方法不一樣的異常。聲明的任何異常必須是被覆蓋方法所聲明異常的同類或子類。
1)爲可恢復的錯誤使用檢查型異常,爲編程錯誤使用非檢查型錯誤。
2)在finally程序塊中關閉或者釋放資源
3)在堆棧跟蹤中包含引發異常的緣由
Java異常類提供了 getCause()方法來檢索致使異常的緣由,這些(緣由)能夠對異常的根層次的緣由提供更多的信息。該Java實踐對在進行調試或排除故障大有幫助。時刻記住,若是你將一個異常包裝成另外一種異常時,構造一個新異常要傳遞源異常。
4)始終提供關於異常的有意義的完整的信息
5)避免過分使用檢查型異常
6)將檢查型異常轉爲運行時異常
這是在像Spring之類的多數框架中用來限制使用檢查型異常的技術之一,大部分出自於JDBC的檢查型異常,都被包裝進DataAccessException中,而(DataAccessException)異常是一種非檢查型異常。這是Java最佳實踐帶來的好處,特定的異常限制到特定的模塊,像 SQLException 放到DAO層,將意思明確的運行時異常拋到客戶層。
7)記住對性能而言,異常代價高昂
須要記住的一件事是異常代價高昂,同時讓你的代碼運行緩慢。假如你有方法從ResultSet(結果集)中進行讀取,這時常會拋出SQLException異常而不會移到下一元素,這將會比不拋出異常的正常代碼執行的慢的多。所以最大限度的減小沒必要要的異常捕捉和移動,那裏沒有什麼固定的緣由。不要僅僅是拋出和捕捉異常,若是你能使用boolean變量去表示執行結果,可能會獲得更整潔,更高性能的解決方案。修正錯誤的根源,避免沒必要需要的異常捕捉。
8)避免catch塊爲空
9)使用標準異常
對於維護性和一致性,不論是如今仍是之後,都是最好的選擇
10)記錄任何方法拋出的異常
Java提供了throw和throws關鍵字來拋出異常,在javadoc中用@throw記錄任何方法可能會拋出的異常。若是你編寫API或者公共接口,這就變得很是重要。任何方法拋出的異常都有相應的文檔記錄,這樣你就能下意識的提醒任何使用(該方法)的人。
答:存在檢查型異常是一個設計上的決定,受到了諸如C++等比Java更早的編程語言設計經驗的影響。絕大多數檢查型異常位於java.io包內,這是合乎情理的,由於在你請求了不存在的系統資源的時候,一段強壯的程序必須可以優雅的處理這種狀況。經過把IOException聲明爲檢查型異常,Java 確保了你可以優雅的對異常進行處理。另外一個可能的理由是,可使用catch或finally來確保數量受限的系統資源(好比文件描述符)在你使用後儘早獲得釋放
答:throws出如今方法聲明中,用來標明該成員函數可能拋出的各類異常
throw出如今方法體中,表示拋出某種異常
答:「異常鏈」是Java中很是流行的異常處理概念,是指在進行一個異常處理時拋出了另一個異常,由此產生了一個異常鏈條。該技術大多用於將「 受檢查異常」 ( checked exception)封裝成爲「非受檢查異常」(unchecked exception)或者RuntimeException。順便說一下,若是由於由於異常你決定拋出一個新的異常,你必定要包含原有的異常,這樣,處理程序才能夠經過getCause()和initCause()方法來訪問異常最終的根源。
答:JDK7中對錯誤(Error)和異常(Exception)處理主要新增長了2個特性,一是在一個catch塊中能夠出來多個異常,就像原來用多個catch塊同樣。另外一個是自動化資源管理(ARM), 也稱爲try-with-resource塊。這2個特性均可以在處理異常時減小代碼量,同時提升代碼的可讀性。
答:final和finally是Java的關鍵字,而finalize則是方法。final關鍵字在建立不可變的類的時候很是有用,只是聲明這個類是final的。而finalize()方法則是垃圾回收器在回收一個對象前調用,但也Java規範裏面沒有保證這個方法必定會被調用。finally關鍵字異常處理相關的關鍵字