### 異常處理--基本概念
? ? 當出現程序無法控制的外部環境問題(用戶提供的文件不存在,文件內容損壞,網絡不可用...)時,JAVA就會用異常對象來描述。
java中用2種方法處理異常:
1、在發生異常的地方直接處理;
2、將異常拋給調用者,讓調用者處理。
### 異常分類
1、檢查性異常:java.lang.Exception
2、運行期異常:java.lang.RuntimeException
3、錯誤:java.lang.Error
頂層是java.lang.Throwable類,檢查性異常、運行期異常、錯誤都是這個類的子孫類,java.lang.Exception和java.lang.Error繼承自java.lang.Throwable,而java.lang.RuntimeException繼承自java.lang.Exception
### 1、檢查性異常:
????程序正確,但因為外在的環境條件不滿足引發。例如:用戶錯誤及I/O問題--程序試圖打開一個并不存在的遠程Socket端口,或者是打開不存在的文件時。這不是程序本身的邏輯錯誤,而很可能是遠程機器名字錯誤(用戶拼寫錯誤),對商用軟件系統,程序開發者必須考慮并處理這個問題。java編譯器強制要求處理這類異常,如果不捕獲這類異常,程序將不能被編譯。
?
### 2、運行期異常:
????這意味著程序存在bug,如數組越界、0被除、入參不滿足規范...這類異常需要更改程序來避免,java編譯器強制要求處理這類異常。
?
### 3、錯誤:
一般很少見,也很難通過程序解決,它可能源于程序的bug,但一般更可能源于環境問題,如內存耗盡。錯誤在程序中無需處理,而由運行環境處理。
?
~~~
//檢測性異常
//當使用IO流時,會有檢查性異常,這時候會報錯,你必須拋出或者是捕獲異常才能通過編譯
try {
FileReader fr = new FileReader("C:\\in.txt");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//運行性異常
//當數組越界,除0操作等等都會導致運行性異常
int[] array = new int[10];
int num = array[11];
num = 10/0;
~~~
?
### 異常處理
### 1、try...catch
程序運行產生異常時,將從異常發生點中斷程序并向外拋出異常信息。
?
~~~
<span style="white-space:pre"> </span>try{
//在出現異常的地方,就終止執行代碼
//然后進入到catch
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
//如果catch語句不止一個,則進入匹配異常那個catch
//實用方面的話,catch語句中用Exception是最簡單的
//可以采用從小到大捕獲異常的思想,性能可能好些,但是較復雜
} catch(Exception e){
e.printStackTrace();
}
~~~
### 2、finally
如果把finally塊置try...catch...語句后,finally塊一般都會得到執行,它相當于一個萬能的保險,即使前面的try塊發生異常,而又沒有對應異常的catch塊,finally塊將馬上執行。
?
以下情形,finally塊將不會被執行:
1、finally塊中發生了異常;
2、程序所在的線程死亡;
3、在前面的代碼中用了System.exit();
4、關閉CPU
?
~~~
<span style="white-space:pre"> </span>try {
br = new BufferedReader(new FileReader("C:\\in.txt"));
} catch(Exception e) {
e.printStackTrace();
} finally {
//不管有沒有異常都會執行
//用來釋放資源,連接等
if(br != null){
try{
br.close();
System.out.println("Buffer流成功關閉");
} catch(Exception e) {
e.printStackTrace();
}
}
}
~~~
?
### 3、throws
將異常拋給調用者,讓調用者處理異常thorws
?
~~~
class Father{
public void work(){
Son son = new Son();
//調用者捕獲異常,如果不想處理,可以拋出異常交給上一層處理,如果都不處理,那么虛擬機進行處理
try {
son.work();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
//當不想catch當前異常時,可以拋出它,讓調用者來捕獲異常
class Son{
public void work() throws Exception{
FileReader fr = new FileReader("C:in.txt");
}
}
~~~
### 4、多個異常的處理規則
????定義多個catch可精確地定位異常。如果為子類的異常定義了特殊的catch塊,而父類的異常則放在另外一個catch塊中,此時,必需滿足以下規則:
????子類異常的處理塊必需在父類異常處理塊的前面,否則會發生編譯錯誤。所以越特殊的異常越在前面處理,越普通的異常越在后面處理。這類似于制訂防火墻的規則次序:較特殊的規則在前,較普通的規則在后。
?
自己也可以定義并拋出異常,方法是2步:
????創建異常,拋出異常(首先實例化一個異常對象,然后用throw拋出)合在一起就是---throw?new?IOException("異常說明信息"),將創建異常,拋出異常合在一起的好處是:創建異常時,會包含異常創建處的行信息,異常被捕獲時可以通過堆棧跡(Stack?Trace)的形式報告這些信息。如果在同一行代碼創建和拋出異常時,對于程序的調試將非常有用。所以,throw?new?XXX()已經成為一個標準的異常拋出范式。在定義一個方法時,方法塊中調用的方法可能會拋出異常,可用上面的throw?new?XXX()處理,如果不處理,那么必需在方法定義時,用throws聲明這個方法全拋出的異常。
對異常的處理,有一條行之有效的默認規則:向上拋出----被調用類在運行過程中對遇到的異常一概不作處理,而是直接向上拋出,一直到最上層的調用類,調用類根據應用系統的需求和特定的異常處理規則進行處理,如向控制臺輸出異常堆棧信息,打印在日志文件中。用一句形象的話來說,就是誰使用,誰(最上層的調用類)處理。
?
-------------參考《韓順平.循序漸進學.java.從入門到精通》
-------------參考《JDK_API_1_6_zh_CN》
Java學習筆記--導航[http://blog.csdn.net/q547550831/article/details/49819641](http://blog.csdn.net/q547550831/article/details/49819641)