異常:在運行時,發生不正常的情況
在java中用類的形式對不正常情況進行了描述和封裝對象
描述不正常情況的類,就稱爲異常類
以前正常流程代碼和問題處理代碼相結合
現在將正常流程代碼和問題處理代碼分離,提高閱讀性
其實異常就是java通過面向對象的思想將問題封裝成了對象,用異常類對其進行描述
不同的問題用不同的類進行具體描述
異常的體系:
問題很多,意味着描述的類也很多,將其向上抽取,形成了異常體系
最終問題(不正常情況)就分成了兩大類:一般不可處理的 和 可處理的兩大類;
在java中,對於不可處理的,一般用Error類來表示,對於 可處理的 , 一般用Exception來示。
Throwable(可拋):無論是error,還是exception,都是問題,問題發生就應該拋出,讓調用者知
道並處理(該體系的特點就在於Throwable及其所有的子類都具有可拋性;對於不具有可拋性的問
題是不能進行拋出的)
可拋性到底是什麼?其實是通過兩個關鍵字來體現的; throws 和 throw這兩個關鍵字,凡是被這
兩個關鍵字所操作的類和對象都具備可拋性。
一般不可處理的。Error
特點:是由jvm拋出的嚴重性問題。這種問題一般不針對進行處理,直接修改程序。
該體系的特點:子類的後綴名都是用其父類名作爲後綴,閱讀性很強。
1. 一般不可處理的。Error
2. 可處理的。Exception
下面的程序爲throw關鍵字示例
class Demo
{
public int method(int[] arr, int index)
{
if (arr == null)
{
throw new NullPointerException("這是一個空指針異常,哥們兒、你太瘋狂啦!");
}
if (index >= arr.length)
{
throw new ArrayIndexOutOfBoundsException("數組的角標越界啦,哥們兒、你是不是瘋啦?");
}
if (index < 0)
{
throw new ArrayIndexOutOfBoundsException("數組的角標不能爲負數,哥們兒、你真的是瘋啦!");
}
return arr[index];
}
}
class ExceptionDemo
{
public static void main(String[] args)
{
int [] arr = new int[]{1,2,3};
Demo d = new Demo();
int num = d.method(arr,2);
System.out.println("這是正確的輸出" + num);
int num1 = d.method(arr,3);
System.out.println("這是異常的情況");
System.out.println("這裏是主程序結束的標誌");
}
}
對於角標是整數不存在,可以用角標越界表示
對於負數爲角標的情況,準備用負數角標異常來表示
負數角標這種異常在java中並沒有定義過,那就按照java異常的創建思想,面向對象,將負數角標進行自定義描述,並封裝成對象。這種自定義的問題描述稱爲自定義異常。
注意:如果讓一個類稱爲一個異常類,則必須繼承異常體系,因爲只有繼承異常體系的子類纔有資格具備可拋性,纔可以被兩個關鍵字所操作(throw 和 throws)
class ArrayFuShuIndexException extends Exception
{
ArrayFuShuIndexException(){}
ArrayFuShuIndexException(String msg)
{
super(msg);
}
}
class Demo1
{
public int method(int[] arr, int index) throws ArrayFuShuIndexException
{
if (arr == null)
{
throw new NullPointerException("這是一個空指針異常,哥們兒、你太瘋狂啦!");
}
if (index >= arr.length)
{
throw new ArrayIndexOutOfBoundsException("數組的角標越界啦,哥們兒、你是不是瘋啦?");
}
if (index < 0)
{
throw new ArrayFuShuIndexException("數組的角標不能爲負數,哥們兒、你真的是瘋啦!");
}
return arr[index];
}
}
class ExceptionDemo1
{
public static void main(String[] args) throws ArrayFuShuIndexException
{
int [] arr = new int[]{1,2,3};
Demo1 d = new Demo1();
int num = d.method(arr,2);
System.out.println("這是正確的輸出" + num);
int num1 = d.method(arr,-1);
System.out.println("這是異常的情況");
System.out.println("這裏是主程序結束的標誌");
}
}
異常(Exception)的分類:
1. 編譯時被檢測的異常:只要是Exception和其子類都是,除了特殊子類RuntimeException體系;編譯時異常問題一旦出現,希望在編譯時就進行檢測,讓這種問題有對應的處理方式,這樣的問題都可以針對性處理
2. 編譯時不檢測的異常(運行時異常):就是Exception中的RuntimeException和其子類;這種問題的發生,無法讓功能繼續,運算無法進行,更多的時候是調度者導致的。或者引發了內部狀態的改變導致的。那麼、這種問題一般不進行處理,直接編譯通過,在運行時,讓調用時的程序強制停止。讓調用者對代碼進行修正。
自定義異常時,要麼繼承Exception,要麼繼承RuntimeException。
Throws 和 throw區別:
1. Throws 使用在函數上;Throw使用在函數內
2. Throws拋出的是異常類,可以拋出多個,用逗號隔開;throw拋出的是異常對象
異常處理的捕捉形式:
這是可以對異常進行針對性的處理方式
異常處理格式:
Try
{放需要被檢測異常的代碼}
Catch(異常類 變量) //該變量用於接收發生的異常對象
{真正處理異常的代碼}
Finally
{一定會被執行的代碼}
class ArrayFuShuIndexException extends Exception
{
ArrayFuShuIndexException(){}
ArrayFuShuIndexException(String msg)
{
super(msg);
}
}
class Demo1
{
public int method(int[] arr, int index) throws ArrayFuShuIndexException
{
if (arr == null)
{
throw new NullPointerException("這是一個空指針異常,哥們兒、你太瘋狂啦!");
}
if (index >= arr.length)
{
throw new ArrayIndexOutOfBoundsException("數組的角標越界啦,哥們兒、你是不是瘋啦?");
}
if (index < 0)
{
throw new ArrayFuShuIndexException("數組的角標不能爲負數,哥們兒、你真的是瘋啦!");
}
return arr[index];
}
}
class ExceptionDemo1
{
public static void main(String[] args)
{
int [] arr = new int[]{1,2,3};
Demo1 d = new Demo1();
int num ;
try
{
num = d.method(arr,-1);
}
catch (ArrayFuShuIndexException e)
{
System.out.println(e.getMessage());
System.out.println("數組角標不能爲負數");
}
catch (ArrayIndexOutOfBoundsException e)
{
System.out.println("數組越界");
}/*
catch (NullPointerException e)
{
System.out.println("傳入的數組爲空指針");
}*/
catch (Exception e)
{
e.printStackTrace();
}
finally
{
System.out.println("程序退出");
System.exit(1);
}
}
}
注意:jvm的異常處理機制默認就是調用printStackStrace方法
但實際上,如果有生成日誌的需求,均是使用第三方工具,例如log4j,log4j即log for java!
注意:在多catch的情況下,父類的catch一定要放在子類的catch之下(代碼上下位置)
異常處理原則;
1. 函數內容如果拋出需要檢測的異常,那麼函數上必須聲明,否則必須在函數內用try catch捕捉,
否則編譯失敗
2. 如果調用到了聲明異常的函數,那麼try catch要麼throws,否則編譯失敗
3. 什麼時候catch,什麼時候throws?
功能內容可以解決,用catch,解決不了,用throws告訴調用者,由調用者解決
4. 一個功能如果拋出多個異常,那麼調用時,必須有多個catch進行針對性的處理;內部有幾個
需要檢測的異常,就拋幾個異常,拋出幾個,就catch幾個!
異常--finally代碼塊:通常用於關閉程序中打開的資源
有一種情況,finally代碼塊不會執行,就是在finally之前執行語句中,包含System.exit()語句。否則、無論是否發生異常,finally都一定會執行。
Try catch finally代碼塊組合特點:
1. Try catch finally
2. Try catch(多個),當沒有必要資源需要釋放的時候,使用這種方式
3. Try finally,可用於當出現異常的時候,確保資源立即釋放掉,對於出現的異常,可能本類無法處理,交給其他的類來進行處理。
Void show() throws Exception
{
Try
{
Throw new Exception();
}
Finally
{}
}
下面是個例子
class Demo2
{
public int method(int[] arr, int index)
{
if (index >= arr.length)
{
throw new ArrayIndexOutOfBoundsException("數組的角標越界啦,哥們兒、你是不是瘋啦?");
}
return arr[index];
}
}
class ExceptionDemo2
{
public static void main(String[] args)
{
int [] arr = new int[]{1,2,3};
Demo2 d = new Demo2();
int num ;
try
{
num = d.method(arr,10);
}
catch (ArrayIndexOutOfBoundsException e)
{
System.out.println("數組越界");
}
finally
{
System.out.println("程序退出");
System.exit(1);
}
}
}
Finally作用很大,例如 實際開發中連接數據庫的代碼,一旦查詢的時候,發生異常,此時就可以在finally中關閉數據庫的連接,如果不關閉,很容易耗盡數據庫的連接資源。
異常應用:
/*
老師用電腦上課
問題領域中涉及兩個對象
老師、電腦
分析其中的問題。
比如電腦藍屏、冒煙啦
*/
class LanPingException extends Exception
{
LanPingException(String msg)
{
super(msg);
}
}
class MaoYanException extends Exception
{
MaoYanException(String msg)
{
super(msg);
}
}
class NoPlanException extends Exception
{
NoPlanException(String msg)
{
super(msg);
}
}
class Computer
{
private int state = 2;
public void run() throws LanPingException,MaoYanException
{
if (state == 1)
{
throw new LanPingException("電腦藍屏啦");
}
if (state == 2)
{
throw new MaoYanException("電腦冒煙啦");
}
System.out.println("老師上課的電腦");
}
public void reset()
{
state = 0;
System.out.println("電腦已經進行重啓");
}
}
class Teacher
{
private String name;
private Computer comp;
Teacher(String name)
{
this.name = name;
comp = new Computer();
}
Teacher(){}
public void prelect() throws NoPlanException
{
try{
comp.run();
System.out.println("講課");
}catch (LanPingException e)
{
System.out.println(e.toString());
comp.reset();
prelect();
}catch (MaoYanException e)
{
System.out.println(e.toString());
test();
throw new NoPlanException("對電腦進行維修,課時任務無法完成");
}
}
public void test()
{
System.out.println("大家開始練習");
}
}
class ExceptionTest
{
public static void main(String[] args)
{
Teacher t = new Teacher("zhangsan");
try
{
t.prelect();
}
catch (NoPlanException e)
{
System.out.println("換人...............");
}
}
}
=====================================================
class NoAddException extends Exception{}
void addData(Data d) throws NoAddException
{
連接數據庫
try
{
添加數據,出現異常 SQLException
}
catch (SQLException e)
{
throw new NoAddException();
}
finally
{
關閉數據庫
}
}
*/
異常注意事項:
1. 子類在覆蓋父類方法時,父類的方法如果拋出了異常,那麼子類的方法只能拋出父類的異常或者該異常的子類。
2. 如果父類拋出多個異常,那麼子類只能拋出父類異常的子集
簡單而言、實就是子類覆蓋父類只能拋出父類的異常或者子集
注意:如果父類的方法沒有拋出異常,那麼子類覆蓋時絕對不能拋。就只能try。
Object:所有類的父類
Object是不斷的抽取,具備着所有對象都具備的共性內容