異常:是在運行時期發(fā)生的不正常情況。。
在java中用類的形式對不正常情況進行了描述和封裝對象。
描述不正常的情況的類,就稱為異常類。
以前正常流程:代碼和問題處理代碼相結(jié)合,
現(xiàn)在將正常流程代碼和問題處理代碼分離。提高閱讀性.
其實異常就是java通過面向?qū)ο蟮乃枷雽栴}封裝成了對象.
用異常類對其進行描述。
不同的問題用不同的類進行具體的描述。 比如角標越界。空指針等等。
問題很多,意味著描述的類也很多,
將其共性進行向上抽取,形成了異常體系。
最終問題(不正常情況)就分成了兩大類。
Throwable:無論是error,還是異常,問題,問題發(fā)生就應(yīng)該可以拋出,讓調(diào)用者知道并處理。
該體系的特點就在于Throwable及其所有的子類都具有可拋性。
可拋性到底指的是什么呢?怎么體現(xiàn)可拋性呢?
其實是通過兩個關(guān)鍵字來體現(xiàn)的。
throws 、throw ,凡是可以被這兩個關(guān)鍵字所操作的類和對象都具備可拋性.
|--1,一般不可處理的。Error
特點:是由jvm拋出的嚴重性的問題。
這種問題發(fā)生一般不針對性處理。直接修改程序
|--2,可以處理的。Exception
該體系的特點:
子類的后綴名都是用其父類名作為后綴,閱讀性很強。
class Demo
{
public int method(int[] arr,int index)
{
if(arr==null)
throw new NullPointerException("數(shù)組的引用不能為空!");
if(index>=arr.length)
{
throw new ArrayIndexOutOfBoundsException("數(shù)組的角標越界啦,哥們,你是不是瘋了?:"+index);
}
if(index<0)
{
throw new ArrayIndexOutOfBoundsException("數(shù)組的角標不能為負數(shù),哥們,你是真瘋了!:"+index);
}
return arr[index];
}
}
class ExceptionDemo2
{
public static void main(String[] args)
{
int[] arr = new int[3];
Demo d = new Demo();
int num = d.method(null,-30);
System.out.println("num="+num);
System.out.println("over");
}
}
內(nèi)存圖:

自定義異常類
比如說:對于角標是正數(shù)不存在,可以用角標越界表示,
對于負數(shù)為角標的情況,準備用負數(shù)角標異常來表示。
但是負數(shù)角標這種異常在java中并沒有定義過。
那就按照java異常的創(chuàng)建思想,面向?qū)ο?,將負?shù)角標進行自定義描述。并封裝成對象。
這種自定義的問題描述成為自定義異常。
注意:如果讓一個類稱為異常類,必須要繼承異常體系,因為只有稱為異常體系的子類才有資格具備可拋性。才可以被兩個關(guān)鍵字所操作,throws throw
自定義異常類代碼實例:
class FuShuIndexException extends Exception
{
FuShuIndexException()
{}
FuShuIndexException(String msg)
{
super(msg);//調(diào)用父類的構(gòu)造方法,使你自定義的異常語句輸出
}
}
異常的分類:
-
編譯時被檢測異常:只要是Exception和其子類都是,除了特殊子類RuntimeException體系。
這種問題一旦出現(xiàn),希望在編譯時就進行檢測,讓這種問題有對應(yīng)的處理方式。
這樣的問題都可以針對性的處理。
-
編譯時不檢測異常(運行時異常):就是Exception中的RuntimeException和其子類。
這種問題的發(fā)生,無法讓功能繼續(xù),運算無法進行,更多是因為調(diào)用者的原因?qū)е碌幕蛘咭l(fā)了
內(nèi)部狀態(tài)的改變導(dǎo)致的。
那么這種問題一般不處理,直接編譯通過,在運行時,讓調(diào)用者調(diào)用時的程序強制停止,讓調(diào)用者
對代碼進行修正。
所以自定義異常時,要么繼承Exception。要么繼承RuntimeException。
throws 和throw的區(qū)別
- throws使用在函數(shù)上。
throw使用在函數(shù)內(nèi)。 - throws拋出的是異常類,可以拋出多個,用逗號隔開。
throw拋出的是異常對象。
異常處理的捕捉形式:
這是可以對異常進行針對性處理的方式。
具體格式是:
try
{
//需要被檢測異常的代碼。
}
catch(異常類 變量)//該變量用于接收發(fā)生的異常對象
{
//處理異常的代碼。
}
finally
{
//一定會被執(zhí)行的代碼。
}
異常處理的原則:
1,函數(shù)內(nèi)容如果拋出需要檢測的異常,那么函數(shù)上必須要聲明。
否則必須在函數(shù)內(nèi)用try...catch捕捉,否則編譯失敗。
2,如果調(diào)用到了聲明異常的函數(shù),要么try...catch,要么throws,否則編譯失敗。
3,什么時候catch,什么時候throws 呢?
功能內(nèi)容可以解決,用catch。
解決不了,用throws告訴調(diào)用者,由調(diào)用者解決 。
4,一個功能如果拋出了多個異常,那么調(diào)用時,必須有對應(yīng)多個catch進行針對性的處理。
內(nèi)部又有個需要檢測的異常,就拋幾個異常,拋出幾個,就catch幾個。
下面有示例代碼:
//自定義異常
class FuShuIndexException extends Exception
{
FuShuIndexException()
{}
FuShuIndexException(String msg)
{
super(msg);
}
}
class Demo
{
//如果是java自帶的異常類,如:NullPointerException,在方法簽名后可以不聲明出來
public int method(int[] arr,int index)throws NullPointerException,FuShuIndexException
{
if(arr==null)
throw new NullPointerException("沒有任何數(shù)組實體");
if(index<0)
throw new FuShuIndexException();
return arr[index];
}
}
class ExceptionDemo4
{
public static void main(String[] args)
{
int[] arr = new int[3];
Demo d = new Demo();
try
{
int num = d.method(null,-1);
System.out.println("num="+num);
}
catch(NullPointerException e)
{
System.out.println(e.toString());
}
catch (FuShuIndexException e)
{
System.out.println("message:"+e.getMessage());
System.out.println("string:"+e.toString());
e.printStackTrace();//jvm默認的異常處理機制就是調(diào)用異常對象的這個方法。
System.out.println("負數(shù)角標異常!!!!");
}
/*
catch(Exception e)//多catch父類的catch放在最下面。
{
}
*/
System.out.println("over");
}
}

try catch finally 代碼塊組合特點:
1,正常使用:
try catch finally
2,
try catch(多個)當(dāng)沒有必要資源需要釋放時,可以不用定義finally。
3,
try finally 異常無法直接catch處理,但是資源需要關(guān)閉。
void show()throws Exception
{
try
{
//開啟資源。
throw new Exception();
}
finally
{
//關(guān)閉資源。
}
/*
catch(Exception e)
{
}
*/
}
舉例:
class Demo
{
public int show(int index)throws ArrayIndexOutOfBoundsException
{
if(index<0)
throw new ArrayIndexOutOfBoundsException("越界啦?。?);
int[] arr = new int[3];
return arr[index];
}
}
class ExceptionDemo5
{
public static void main(String[] args)
{
Demo d = new Demo();
try
{
int num = d.show(-1);
System.out.println("num="+num);
}
catch (ArrayIndexOutOfBoundsException e)
{
System.out.println(e.toString());
// return ;
// System.exit(0);//退出jvm。
}
finally//通常用于關(guān)閉(釋放)資源。
{
System.out.println("finally");
}
System.out.println("over");
}
}
/*
連接數(shù)據(jù)庫
查詢。Exception
關(guān)閉連接。
*/
實例
/*
畢老師用電腦上課。
問題領(lǐng)域中涉及兩個對象。
畢老師,電腦。
分析其中的問題。
比如電腦藍屏啦。冒煙啦。
*/
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();
}
public void prelect()throws NoPlanException
{
try
{
comp.run();
System.out.println(name+"講課");
}
catch (LanPingException e)
{
System.out.println(e.toString());
comp.reset();
prelect();
}
catch (MaoYanException e)
{
System.out.println(e.toString());
test();
//可以對電腦進行維修。
// throw e;
throw new NoPlanException("課時進度無法完成,原因:"+e.getMessage());
}
}
public void test()
{
System.out.println("大家練習(xí)");
}
}
class ExceptionTest
{
public static void main(String[] args)
{
Teacher t = new Teacher("畢老師");
try
{
t.prelect();
}
catch (NoPlanException e)
{
System.out.println(e.toString()+"......");
System.out.println("換人");
}
}
}
/*
class NoAddException extends Exception
{}
void addData(Data d)throws NoAddException
{
連接數(shù)據(jù)庫
try
{
添加數(shù)據(jù)。出現(xiàn)異常 SQLException();
}
catch(SQLException e)
{
//處理代碼。
throw new NoAddException();
}
fianlly
{
關(guān)閉數(shù)據(jù)庫。
}
}
*/
異常的注意事項:
1,子類在覆蓋父類方法時,父類的方法如果拋出了異常,
那么子類的方法只能拋出父類的異?;蛘咴摦惓5淖宇悺?/p>
2,如果父類拋出多個異常,那么子類只能拋出父類異常的子集。
簡單說:子類覆蓋父類只能拋出父類的異常或者子類或者子集。
注意:如果父類的方法沒有拋出異常,那么子類覆蓋時絕對不能拋,就只能try