Java語言基礎(chǔ)學(xué)習(xí)異常處理

一盈罐、異常概述與異常體系結(jié)構(gòu)

1.異常:在Java語言中藻三,將程序執(zhí)行中發(fā)生的不正常情況稱為“異忱嬲觯”。 (開發(fā)過程中的語法錯(cuò)誤和邏輯錯(cuò)誤不是異常)

2.?異常體系結(jié)構(gòu)

java.lang.Throwable

|-----java.lang.Error:一般不編寫針對性的代碼進(jìn)行處理昨寞。

|-----java.lang.Exception:可以進(jìn)行異常的處理。

|--------------編譯時(shí)異常(checked)

|-------------------IOException

|--------------------------FileNotFoundException

|-------------------ClassNotFoundException

|--------------運(yùn)行時(shí)異常(unchecked,RuntimeException)

|-------------------NullPointerException空指針異常

|-------------------ArrayIndexOutOfBoundsException數(shù)組角標(biāo)越界

|-------------------ClassCastException類型轉(zhuǎn)換異常

|-------------------NumberFormatException數(shù)值類型異常

|-------------------InputMismatchException輸入不匹配異常

|-------------------ArithmeticException算術(shù)異常

public class ExceptionTest {


? //******************以下是編譯時(shí)異常***************************

? @Test

? public void test7(){

// File file = new File("hello.txt");

// FileInputStream fis = new FileInputStream(file);

//

// int data = fis.read();

// while(data != -1){

// System.out.print((char)data);

// data = fis.read();

// }

//

// fis.close();


? }


? //******************以下是運(yùn)行時(shí)異常***************************

? //ArithmeticException

? @Test

? public void test6(){

? ? int a = 10;

? ? int b = 0;

? ? System.out.println(a / b);

? }


? //InputMismatchException

? @Test

? public void test5(){

? ? Scanner scanner = new Scanner(System.in);

? ? int score = scanner.nextInt();

? ? System.out.println(score);


? ? scanner.close();

? }


? //NumberFormatException

? @Test

? public void test4(){


? ? String str = "123";

? ? str = "abc";

? ? int num = Integer.parseInt(str);




? }


? //ClassCastException

? @Test

? public void test3(){

? ? Object obj = new Date();

? ? String str = (String)obj;

? }


? //IndexOutOfBoundsException

? @Test

? public void test2(){

? ? //ArrayIndexOutOfBoundsException

// int[] arr = new int[10];

// System.out.println(arr[10]);

? ? //StringIndexOutOfBoundsException

? ? String str = "abc";

? ? System.out.println(str.charAt(3));

? }


? //NullPointerException

? @Test

? public void test1(){


// int[] arr = null;

// System.out.println(arr[3]);


? ? String str = "abc";

? ? str = null;

? ? System.out.println(str.charAt(0));


? }

}

Java程序在執(zhí)行過程中所發(fā)生的異常事件可分為兩類:

Error:Java虛擬機(jī)無法解決的嚴(yán)重問題。如:JVM系統(tǒng)內(nèi)部錯(cuò)誤援岩、資源 耗盡等嚴(yán)重情況歼狼。比如:StackOverflowError和OOM。一般不編寫針對性 的代碼進(jìn)行處理享怀。

public class ErrorTest {

? public static void main(String[] args) {

? ? //1.棧溢出:java.lang.StackOverflowError

//? main(args);

? ? //2.堆溢出:java.lang.OutOfMemoryError

? ? Integer[] arr = new Integer[1024*1024*1024];


? }

}

Exception: 其它因編程錯(cuò)誤或偶然的外在因素導(dǎo)致的一般性問題羽峰,可以使 用針對性的代碼進(jìn)行處理。例如: ?空指針訪問 ?試圖讀取不存在的文件 ?網(wǎng)絡(luò)連接中斷 ?數(shù)組角標(biāo)越界凹蜈。

3.對于這些錯(cuò)誤限寞,一般有兩種解決方法:一是遇到錯(cuò)誤就終止程序 的運(yùn)行。另一種方法是由程序員在編寫程序時(shí)仰坦,就考慮到錯(cuò)誤的 檢測履植、錯(cuò)誤消息的提示,以及錯(cuò)誤的處理悄晃。

捕獲錯(cuò)誤最理想的是在編譯期間玫霎,但有的錯(cuò)誤只有在運(yùn)行時(shí)才會發(fā)生。 比如:除數(shù)為0妈橄,數(shù)組下標(biāo)越界等 ? 分類:編譯時(shí)異常和運(yùn)行時(shí)異常

運(yùn)行時(shí)異常

是指編譯器不要求強(qiáng)制處置的異常庶近。一般是指編程時(shí)的邏輯錯(cuò)誤,是程序 員應(yīng)該積極避免其出現(xiàn)的異常眷蚓。java.lang.RuntimeException類及它的子?類都是運(yùn)行時(shí)異常鼻种。

對于這類異常,可以不作處理沙热,因?yàn)檫@類異常很普遍叉钥,若全處理可能會對 程序的可讀性和運(yùn)行效率產(chǎn)生影響。

編譯時(shí)異常

是指編譯器要求必須處置的異常篙贸。即程序在運(yùn)行時(shí)由于外界因素造成的一 般性異常投队。編譯器要求Java程序必須捕獲或聲明所有編譯時(shí)異常。

對于這類異常爵川,如果程序不處理敷鸦,可能會帶來意想不到的結(jié)果。

異常處理機(jī)制

Java采用的異常處理機(jī)制寝贡,是將異常處理的程序代碼集中在一起扒披, 與正常的程序代碼分開,使得程序簡潔圃泡、優(yōu)雅谎碍,并易于維護(hù)。

關(guān)于異常對象的產(chǎn)生:① 系統(tǒng)自動生成的異常對象

異常的處理:抓拋模型

?過程一:"拋":程序在正常執(zhí)行的過程中洞焙,一旦出現(xiàn)異常蟆淀,就會在異常代碼處生成一個(gè)對應(yīng)異常類的對象拯啦。并將此對象拋出。?一旦拋出對象以后熔任,其后的代碼就不再執(zhí)行褒链。

過程二:"抓":可以理解為異常的處理方式:① try-catch-finally ② throws。

方式一:try-catch-finally的使用(Alt+Shift+Z)

try{

? //可能出現(xiàn)異常的代碼

? }catch(異常類型1 變量名1){

//處理異常的方式1

? }catch(異常類型2 變量名2){

//處理異常的方式2

}catch(異常類型3 變量名3){

? //處理異常的方式3

}

? ....

finally{

? //一定會執(zhí)行的代碼

}

1. finally是可選的疑苔。

2. 使用try將可能出現(xiàn)異常代碼包裝起來甫匹,在執(zhí)行過程中,一旦出現(xiàn)異常惦费,就會生成一個(gè)對應(yīng)異常類的對象,根據(jù)此對象的類型薪贫,去catch中進(jìn)行匹配。

3. 一旦try中的異常對象匹配到某一個(gè)catch時(shí)瞧省,就進(jìn)入catch中進(jìn)行異常的處理。一旦處理完成鞍匾,就跳出當(dāng)前的try-catch結(jié)構(gòu)(在沒有寫finally的情況)交洗。繼續(xù)執(zhí)行其后的代碼构拳。

4. catch中的異常類型如果沒有子父類關(guān)系,則誰聲明在上梁棠,誰聲明在下無所謂。catch中的異常類型如果滿足子父類關(guān)系掰茶,則要求子類一定聲明在父類的上面蜜笤。否則,報(bào)錯(cuò)把兔。

5. 常用的異常對象處理的方式: ① String getMessage() ② printStackTrace()

getMessage() 獲取異常信息,返回字符串?printStackTrace() 獲取異常類名和異常信息县好,以及異常出 現(xiàn)在程序中的位置。返回值void缕贡。

printStackTrace() 獲取異常類名和異常信息翁授,以及異常出 現(xiàn)在程序中的位置拣播。返回值void。

6. 在try結(jié)構(gòu)中聲明的變量收擦,再出了try結(jié)構(gòu)以后贮配,就不能再被調(diào)用。7. try-catch-finally結(jié)構(gòu)可以嵌套塞赂。

public class ExceptionTest1 {


? @Test

? public void test2(){

? ? try{

? ? ? File file = new File("hello.txt");

? ? ? FileInputStream fis = new FileInputStream(file);


? ? ? int data = fis.read();

? ? ? while(data != -1){

? ? ? ? System.out.print((char)data);

? ? ? ? data = fis.read();

? ? ? }


? ? ? fis.close();

? ? }catch(FileNotFoundException e){

? ? ? e.printStackTrace();

? ? }catch(IOException e){

? ? ? e.printStackTrace();

? ? }

? }


? @Test

? public void test1(){


? ? String str = "123";

? ? str = "abc";

? ? int num = 0;

? ? try{

? ? ? num = Integer.parseInt(str);


? ? ? System.out.println("hello-----1");

? ? }catch(NumberFormatException e){

// System.out.println("出現(xiàn)數(shù)值轉(zhuǎn)換異常了泪勒,不要著急....");

? ? ? //String getMessage():

// System.out.println(e.getMessage());

? ? ? //printStackTrace():

? ? ? ? e.printStackTrace();

? ? }catch(NullPointerException e){

? ? ? System.out.println("出現(xiàn)空指針異常了,不要著急....");

? ? }catch(Exception e){

? ? ? System.out.println("出現(xiàn)異常了宴猾,不要著急....");


? ? }

? ? System.out.println(num);


? ? System.out.println("hello-----2");

? }

}

try-catch-finally中finally的使用:

1.finally是可選的

2.finally中聲明的是一定會被執(zhí)行的代碼圆存。即使catch中又出現(xiàn)異常了,try中有return語句仇哆,catch中有return語句等情況沦辙。

3.像數(shù)據(jù)庫連接、輸入輸出流税产、網(wǎng)絡(luò)編程Socket等資源怕轿,JVM是不能自動的回收的,我們需要自己手動的進(jìn)行資源的?釋放辟拷。此時(shí)的資源釋放撞羽,就需要聲明在finally中。

public class FinallyTest {



? @Test//3

? public void test2(){

? ? FileInputStream fis = null;

? ? try {

? ? ? File file = new File("hello1.txt");

? ? ? fis = new FileInputStream(file);


? ? ? int data = fis.read();

? ? ? while(data != -1){

? ? ? ? System.out.print((char)data);

? ? ? ? data = fis.read();

? ? ? }



? ? } catch (FileNotFoundException e) {

? ? ? e.printStackTrace();

? ? } catch (IOException e) {

? ? ? e.printStackTrace();

? ? }finally{

? ? ? try {

? ? ? ? if(fis != null)

? ? ? ? ? fis.close();

? ? ? } catch (IOException e) {

? ? ? ? e.printStackTrace();

? ? ? }

? ? }

? }


? @Test//2

? public void testMethod(){

? ? int num = method();

? ? System.out.println(num);

? }


? public int method(){


? ? try{

? ? ? int[] arr = new int[10];

? ? ? System.out.println(arr[10]);

? ? ? return 1;

? ? }catch(ArrayIndexOutOfBoundsException e){

? ? ? e.printStackTrace();

? ? ? return 2;

? ? }finally{

? ? ? System.out.println("我一定會被執(zhí)行");

? ? ? return 3;//3

? ? }

? }


? @Test//1

? public void test1(){

? ? try{

? ? ? int a = 10;

? ? ? int b = 0;

? ? ? System.out.println(a / b);


? ? }catch(ArithmeticException e){

? ? ? e.printStackTrace();


// int[] arr = new int[10];

// System.out.println(arr[10]);


? ? }catch(Exception e){

? ? ? e.printStackTrace();

? ? }

// System.out.println("我好帥吧蓝场>魑伞!隅俘!~~");


? ? finally{

? ? ? System.out.println("我好帥啊~~");

? ? }

? }

}


使用try-catch-finally處理編譯時(shí)異常邻奠,使得程序在編譯時(shí)就不再報(bào)錯(cuò),但是運(yùn)行時(shí)仍可能報(bào)錯(cuò)为居。相當(dāng)于我們使用try-catch-finally將一個(gè)編譯時(shí)可能出現(xiàn)的異常碌宴,延遲到運(yùn)行時(shí)出現(xiàn)。

開發(fā)中蒙畴,由于運(yùn)行時(shí)異常比較常見贰镣,所以我們通常就不針對運(yùn)行時(shí)異常編寫try-catch-finally了。

* 針對于編譯時(shí)異常膳凝,我們說一定要考慮異常的處理碑隆。

方式二:throws + 異常類型

"throws + 異常類型"寫在方法的聲明處。指明此方法執(zhí)行時(shí)蹬音,可能會拋出的異常類型上煤。

一旦當(dāng)方法體執(zhí)行時(shí)著淆,出現(xiàn)異常拴疤,仍會在異常代碼處生成一個(gè)異常類的對象嘉熊,此對象滿足throws后異常類型時(shí),就會被拋出凫佛。異常代碼后續(xù)的代碼孕惜,就不再執(zhí)行!

public class ExceptionTest2 {



? public static void main(String[] args){

? ? try{

? ? ? method2();


? ? }catch(IOException e){

? ? ? e.printStackTrace();

? ? }


// method3();


? }



? public static void method3(){

? ? try {

? ? ? method2();

? ? } catch (IOException e) {

? ? ? e.printStackTrace();

? ? }

? }



? public static void method2() throws IOException{

? ? method1();

? }



? public static void method1() throws FileNotFoundException,IOException{

? ? File file = new File("hello1.txt");

? ? FileInputStream fis = new FileInputStream(file);


? ? int data = fis.read();

? ? while(data != -1){

? ? ? System.out.print((char)data);

? ? ? data = fis.read();

? ? }


? ? fis.close();


? ? System.out.println("hahaha!");

? }

}

② 手動的生成一個(gè)異常對象毫炉,并拋出(throw)

public class StudentTest {


? public static void main(String[] args) {

? ? try {

? ? ? Student s = new Student();

? ? ? s.regist(-1001);

? ? ? System.out.println(s);

? ? } catch (Exception e) {

// e.printStackTrace();

? ? ? System.out.println(e.getMessage());

? ? }

? }

}

class Student{


? private int id;


? public void regist(int id) throws Exception {

? ? if(id > 0){

? ? ? this.id = id;

? ? }else{

// System.out.println("您輸入的數(shù)據(jù)非法削罩!");

? ? ? //手動拋出異常對象

// throw new RuntimeException("您輸入的數(shù)據(jù)非法!");

// throw new Exception("您輸入的數(shù)據(jù)非法进陡!");

? ? ? throw new MyException("不能輸入負(fù)數(shù)");

? ? ? //錯(cuò)誤的

// throw new String("不能輸入負(fù)數(shù)");

? ? }

? }

? @Override

? public String toString() {

? ? return "Student [id=" + id + "]";

? }

}

總結(jié): try-catch-finally:真正的將異常給處理掉了微服。

?throws的方式只是將異常拋給了方法的調(diào)用者。 并沒有真正將異常處理掉糙麦。

?4.開發(fā)中如何選擇使用try-catch-finally 還是使用throws丛肮?

如果父類中被重寫的方法沒有throws方式處理異常,則子類重寫的方法也不能使用throws焚廊,意味著如果子類重寫的方法中有異常伴鳖,必須使用try-catch-finally方式處理徙硅。

執(zhí)行的方法a中,先后又調(diào)用了另外的幾個(gè)方法须肆,這幾個(gè)方法是遞進(jìn)關(guān)系執(zhí)行的。我們建議這幾個(gè)方法使用throws的方式進(jìn)行處理豌汇。而執(zhí)行的方法a可以考慮使用try-catch-finally方式進(jìn)行處理。

5.如何自定義異常類宛徊?

(1). 繼承于現(xiàn)有的異常結(jié)構(gòu):RuntimeException 逻澳、Exception(必須顯示處理異常)

(2). 提供全局常量:serialVersionUID

(3). 提供重載的構(gòu)造器

public class MyException extends Exception{


? static final long serialVersionUID = -7034897193246939L;


? public MyException(){


? }


? public MyException(String msg){

? ? super(msg);

? }

}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市苞氮,隨后出現(xiàn)的幾起案子瓤逼,更是在濱河造成了極大的恐慌,老刑警劉巖贷帮,帶你破解...
    沈念sama閱讀 218,122評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件定硝,死亡現(xiàn)場離奇詭異,居然都是意外死亡诲侮,警方通過查閱死者的電腦和手機(jī)箱蟆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評論 3 395
  • 文/潘曉璐 我一進(jìn)店門空猜,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人辈毯,你說我怎么就攤上這事《坌祝” “怎么了唁影?”我有些...
    開封第一講書人閱讀 164,491評論 0 354
  • 文/不壞的土叔 我叫張陵掂名,是天一觀的道長饺蔑。 經(jīng)常有香客問我嗜诀,道長,這世上最難降的妖魔是什么隆敢? 我笑而不...
    開封第一講書人閱讀 58,636評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮筑公,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘匣屡。我一直安慰自己,他們只是感情好誉结,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,676評論 6 392
  • 文/花漫 我一把揭開白布券躁。 她就那樣靜靜地躺著,像睡著了一般以舒。 火紅的嫁衣襯著肌膚如雪慢哈。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,541評論 1 305
  • 那天滥沫,我揣著相機(jī)與錄音键俱,去河邊找鬼。 笑死缀辩,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的雌澄。 我是一名探鬼主播镐牺,決...
    沈念sama閱讀 40,292評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼睬涧,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了畦浓?” 一聲冷哼從身側(cè)響起检疫,我...
    開封第一講書人閱讀 39,211評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎夺溢,沒想到半個(gè)月后烛谊,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,655評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡状勤,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,846評論 3 336
  • 正文 我和宋清朗相戀三年持搜,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了焙矛。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,965評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡剪返,死狀恐怖邓梅,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情日缨,我是刑警寧澤,帶...
    沈念sama閱讀 35,684評論 5 347
  • 正文 年R本政府宣布面哥,位于F島的核電站,受9級特大地震影響尚卫,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜刹泄,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,295評論 3 329
  • 文/蒙蒙 一怎爵、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧姆蘸,春花似錦、人聲如沸乞旦。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,894評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽玖姑。三九已至慨菱,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間符喝,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,012評論 1 269
  • 我被黑心中介騙來泰國打工畏腕, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留茉稠,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,126評論 3 370
  • 正文 我出身青樓铭污,卻偏偏與公主長得像,于是被迫代替她去往敵國和親嘹狞。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,914評論 2 355