1. 程式人生 > >Java執行時異常和非執行時異常

Java執行時異常和非執行時異常

1.Java異常機制

Java把異常當做物件來處理,並定義一個基類java.lang.Throwable作為所有異常的超類。Java中的異常分為兩大類:錯誤Error和異常Exception,Java異常體系結構如下圖所示:


圖片來源:http://blog.csdn.net/wuwenxiang91322/article/details/10346337

2.Throwable

Throwable類是所有異常或錯誤的超類,它有兩個子類:Error和Exception,分別表示錯誤和異常。其中異常Exception分為執行時異常(RuntimeException)和非執行時異常,也稱之為不檢查異常(Unchecked Exception)和檢查異常(Checked Exception)。

3.Error

一般是指java虛擬機器相關的問題,如系統崩潰、虛擬機器出錯誤、動態連結失敗等,這種錯誤無法恢復或不可能捕獲,將導致應用程式中斷,通常應用程式無法處理這些錯誤,因此應用程式不應該捕獲Error物件,也無須在其throws子句中宣告該方法丟擲任何Error或其子類。

4.可查異常和不可查異常

通常,Java的異常(包括Exception和Error)分為可查的異常(checked exceptions)和不可查的異常(unchecked exceptions)。
可查異常(編譯器要求必須處置的異常):正確的程式在執行中,很容易出現的、情理可容的異常狀況。可查異常雖然是異常狀況,但在一定程度上它的發生是可以預計的,而且一旦發生這種異常狀況,就必須採取某種方式進行處理。
除了RuntimeException及其子類以外,其他的Exception類及其子類都屬於可查異常。這種異常的特點是Java編譯器會檢查它,也就是說,當程式中可能出現這類異常,要麼用try-catch語句捕獲它,要麼用throws子句宣告丟擲它,否則編譯不會通過。
不可查異常(編譯器不要求強制處置的異常):包括執行時異常(RuntimeException與其子類)和錯誤(Error)。

如果使用throw在方法體中丟擲可查異常,則需要在方法頭部宣告方法可能丟擲的異常型別。程式會在throw語句後立即終止,它後面的語句執行不到,然後在包含它的所有try塊中(可能在上層呼叫函式中)從裡向外尋找含有與其匹配的catch子句的try塊。

5.執行時異常和非執行時異常

(1)執行時異常都是RuntimeException類及其子類異常,如NullPointerException、IndexOutOfBoundsException等,這些異常是不檢查異常,程式中可以選擇捕獲處理,也可以不處理。這些異常一般是由程式邏輯錯誤引起的,程式應該從邏輯角度儘可能避免這類異常的發生。

當出現RuntimeException的時候,我們可以不處理。當出現這樣的異常時,總是由虛擬機器接管。比如:我們從來沒有人去處理過NullPointerException異常,它就是執行時異常,並且這種異常還是最常見的異常之一。 
出現執行時異常後,如果沒有捕獲處理這個異常(即沒有catch),系統會把異常一直往上層拋,一直到最上層,如果是多執行緒就由Thread.run()丟擲,如果是單執行緒就被main()丟擲。丟擲之後,如果是執行緒,這個執行緒也就退出了。如果是主程式丟擲的異常,那麼這整個程式也就退出了。執行時異常是Exception的子類,也有一般異常的特點,是可以被catch塊處理的。只不過往往我們不對他處理罷了。也就是說,你如果不對執行時異常進行處理,那麼出現執行時異常之後,要麼是執行緒中止,要麼是主程式終止

。 
如果不想終止,則必須捕獲所有的執行時異常,決不讓這個處理執行緒退出。佇列裡面出現異常資料了,正常的處理應該是把異常資料捨棄,然後記錄日誌。不應該由於異常資料而影響下面對正常資料的處理。


(2)非執行時異常是RuntimeException以外的異常,型別上都屬於Exception類及其子類。如IOException、SQLException等以及使用者自定義的Exception異常。對於這種異常,JAVA編譯器強制要求我們必需對出現的這些異常進行catch並處理,否則程式就不能編譯通過。所以,面對這種異常不管我們是否願意,只能自己去寫一大堆catch塊去處理可能的異常。

6.finally關鍵字

來看看下面這個test1()方法:

  1. publicint test1() {  
  2.         try {  
  3.             return1;  
  4.         } finally {  
  5.             return2;  
  6.         }  
  7.     }  
方法test1將返回2;

怎麼解釋呢?再來看看下面這個test2()方法:

  1. publicint test2() {  
  2.         int i = 1;  
  3.         try {  
  4.             System.out.println("try語句塊中");  
  5.             return1;  
  6.         } finally {  
  7.             System.out.println("finally語句塊中");  
  8.             return2;  
  9.         }  
  10.     }  
執行結果是:

try語句塊中
finally語句塊中
2

從執行結果中可以發現,try中的return語句呼叫的函式先於finally中呼叫的函式執行,也就是說return語句先執行,finally語句後執行,所以,返回的結果是2。return並不是讓函式馬上返回,而是return語句執行後,將把返回結果放置進函式棧中,此時函式並不是馬上返回,它要執行finally語句後才真正開始返回。


常見RuntimeException

ArrayStoreException                試圖將錯誤型別的物件儲存到一個物件陣列時丟擲的異常
ClassCastException                試圖將物件強制轉換為不是例項的子類時,丟擲該異常
IllegalArgumentException         丟擲的異常表明向方法傳遞了一個不合法或不正確的引數
IndexOutOfBoundsException   指示某排序索引(例如對陣列、字串或向量的排序)超出範圍時丟擲
NoSuchElementException       表明列舉中沒有更多的元素
NullPointerException                當應用程式試圖在需要物件的地方使用 null 時,丟擲該異常