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

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

try catch finally 代碼塊組合特點(diǎn):
1,正常使用:
try catch finally
2,
try catch(多個(gè))當(dāng)沒有必要資源需要釋放時(shí),可以不用定義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)閉連接。
*/
實(shí)例
/*
畢老師用電腦上課。
問題領(lǐng)域中涉及兩個(gè)對(duì)象。
畢老師,電腦。
分析其中的問題。
比如電腦藍(lán)屏啦。冒煙啦。
*/
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("電腦藍(lán)屏啦??!");
if(state==2)
throw new MaoYanException("電腦冒煙啦??!");
System.out.println("電腦運(yùn)行");
}
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();
//可以對(duì)電腦進(jìn)行維修。
// throw e;
throw new NoPlanException("課時(shí)進(jìn)度無法完成,原因:"+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ù)庫。
}
}
*/
異常的注意事項(xiàng):
1,子類在覆蓋父類方法時(shí),父類的方法如果拋出了異常,
那么子類的方法只能拋出父類的異?;蛘咴摦惓5淖宇悺?/p>
2,如果父類拋出多個(gè)異常,那么子類只能拋出父類異常的子集。
簡(jiǎn)單說:子類覆蓋父類只能拋出父類的異?;蛘咦宇惢蛘咦蛹?/p>
注意:如果父類的方法沒有拋出異常,那么子類覆蓋時(shí)絕對(duì)不能拋,就只能try