Java例外機制
例外
例外是程式中的一些錯誤,但并不是所有的錯誤都是例外,并且錯誤有時候是可以避免的,
例外的分類:
- 檢查性例外:最具代表的檢查性例外是用戶錯誤或問題引起的例外,這是程式員無法預見的,例如要打開一個不存在檔案時,一個例外就發生了,這些例外在編譯時不能被簡單地忽略,
- 運行時例外: 運行時例外是可能被程式員避免的例外,與檢查性例外相反,運行時例外可以在編譯時被忽略,
- 錯誤(Error): 錯誤不是例外,而是脫離程式員控制的問題,錯誤在代碼中通常被忽略,例如,當堆疊溢位時,一個錯誤就發生了,在編譯時同樣檢查不到,
示例:
package com.wmwx.exception;
public class Demo01 {
public static void main(String[] args) {
new Demo01().a(); //拋出例外:StackOverflowError
System.out.println(11/0); //拋出例外:ArithmeticException
System.out.println() //拋出例外:Error
}
public void a(){
b();
}
public void b(){
a();
}
}
例外體系結構
Java把例外當做物件來處理,并定義了一個基類java.lang.Throwable作為所有例外的超類,這些例外分為兩大類,即例外(Exception)和錯誤(Error),其中,Exception類有兩個主要的子類,即 IOException 類和 RuntimeException 類,
Error
Error類物件由虛擬機生成并拋出,大多數錯誤與代碼撰寫者所執行的操作無關,
常見的錯誤如Java虛擬機運行錯誤(VirtualMachineError),當JVM不再有繼續執行操作所需的記憶體資源時,將出現OutOfMemoryError,這些例外發生時,Java虛擬機一般會選擇將執行緒中止,
還有發生在虛擬機試圖執行應用時的錯誤,如類定義錯誤(NoClassDefFoundError)、鏈接錯誤(LinkageError)等,這些錯誤是不可查的,因為它們在應用程式的控制和處理程式能力之外,而且絕大多數是程式運行時不允許出現的狀況,
Exception
在Exception類的分支中有一個重要的子類 RuntimeException(運行時例外),其中包含以下例外:
-
ArrayIndexOutOfBoundsException(陣列下標越界)
-
NullPointerException(空指標例外)
-
ArithmeticException(算術例外)
-
MissingResourceException(丟失資源)
-
ClassNotFoundException(找不到類)
這些例外是不檢查例外,程式中可以選擇捕獲處理,也可以不處理,這些例外一般是由程式邏輯錯誤引起的,程式應該從邏輯角度盡可能避免這類例外的發生,
Error和Exception的區別:
- Error 通常是災難性的致命的錯誤,是程式無法控制和處理的,當出現這些例外時,Java虛擬機(JVM)一般會選擇終止執行緒
- Exception 通常情況下是可以被程式處理的,并且在程式中應該盡可能的去處理這些例外,
捕獲例外
使用 try 和 catch 關鍵字可以捕獲例外,try/catch 代碼塊放在例外可能發生的地方,
try/catch代碼塊中的代碼稱為保護代碼,其基本語法如下:
try
{
// 程式代碼
}catch(ExceptionName e1)
{
// Catch 塊
}catch(ExceptionName e2) //e2需比e1范圍更大
{
// Catch 塊
}finally {
// 終究會執行
}
示例:
package com.wmwx.exception;
public class Demo02 {
public static void main(String[] args) {
int a = 11;
int b = 0;
//快捷鍵 ctrl+alt+T
try{ //try 監控區域
System.out.println(a/b);
}catch (ArithmeticException e){ //catch 捕獲例外(引數是例外型別)
System.out.println("程式出現例外,變數b不能為0!");
}finally { //finally 善后作業
System.out.println("finally終究會被執行,");
}
try{ //監控區域
new Demo02().a();
}catch (StackOverflowError e){ //捕獲例外,多個類別需要從小到大
System.out.println("StackOverflowError"); //會輸出
}catch (Exception e){
System.out.println("Exception"); //不會輸出
}catch (Throwable t){
System.out.println("Throwable"); //不會輸出
}finally { //善后作業
System.out.println("finally終究會被執行,");
}
}
public void a(){
b();
}
public void b(){
a();
}
}
拋出例外
如果一個方法沒有捕獲到一個檢查性例外,那么該方法必須使用 throws 關鍵字來宣告,throws 關鍵字放在方法簽名的尾部,
也可以使用 throw 關鍵字拋出一個例外,無論它是新實體化的還是剛捕獲到的,
注意:兩種方式的拼寫不同,第一種末尾有 s,第二種沒有,
示例:
package com.wmwx.exception;
public class Demo03 {
public static void main(String[] args) {
int a = 11;
int b = 0;
try {
new Demo03().devide(a, b);
} catch (ArithmeticException e) {
e.printStackTrace();
} finally {
}
}
//假設在方法中無法處理例外,可以用throws主動拋出例外
public void devide(int a, int b) throws ArithmeticException{
if (b==0){
throw new ArithmeticException(); //使用throw主動拋出例外,一般用在方法中
}
System.out.println(a / b);
}
}
自定義例外
使用Java內置的例外類可以描述在編程時出現的大部分例外精況,除此之外,用戶還可以自定義例外,只需繼承Exception類即可,
示例:
MyException類(自定義例外類):
package com.wmwx.exception;
//自定義的例外類
public class MyException extends Exception{
//假設:當傳遞過來的數字大于10時拋出例外
private int detail;
//構造方法
public MyException(int a) {
this.detail = a;
}
//toString 列印例外資訊
@Override
public String toString() {
return "MyException{detail=" + detail + "}";
}
}
Demo04類(測驗類):
package com.wmwx.exception;
//自定義例外的測驗類
public class Demo04 {
//可能會存在例外的方法
public void test(int a) throws MyException {
System.out.println("傳遞的引數為:"+a);
if (a>10){
throw new MyException(a); //拋出例外
}
System.out.println("沒有例外!");
}
public static void main(String[] args) {
try {
new Demo04().test(5); //沒有例外
new Demo04().test(15); //有例外
} catch (MyException e) {
System.out.println("MyException => " + e);
}
}
}
經驗總結
- 處理運行時例外時,采用邏輯去合理規避,同時輔助 try-catch 處理,
- 在多重catch塊后面,可以加一個 catch (Exception) 來處理可能會被遺漏的例外,對于不確定的代碼,也可以加上try-catch,處理潛在的例外,
- 盡量去處理例外,切忌只是簡單地呼叫 printStackTrace() 去列印輸出,具體如何處理例外,要根據不同的業務需求和例外型別去決定,
- 盡量添加 finally 陳述句塊去釋放占用的資源,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/265051.html
標籤:其他
