摘要:例如將型對象轉(zhuǎn)換為類拋出的異常表明向方法傳遞了一個不合法或不正確的參數(shù)。應(yīng)用程序可以將此類子類化以指示類似的異常。用非法索引訪問數(shù)組時拋出的異常。
第四階段 IO 異常處理
沒有完美的程序,所以我們需要不斷地完善,考慮各種可能性,我們要將除了自己以外的任何用戶或者操作者都當(dāng)成傻子來考慮問題(一) 概述及體系 (1) 概述在我們開發(fā)過程中 我們運(yùn)行時常常會遇到 這樣java.lang.XxxException的信息,這代表程序發(fā)生了一些錯誤,也叫作異常
異常情形是指阻止當(dāng)前方法或者作用域繼續(xù)執(zhí)行的問題 ——《Think in Java》
簡單概括:程序出現(xiàn)不正常情況后,程序?qū)霎?dāng)前環(huán)境,并且拋出異常。
(2) 體系(1) Error —— 錯誤:程序無法處理的嚴(yán)重錯誤,我們不作處理
這種錯誤一般來說與操作者無關(guān),并且開發(fā)者與應(yīng)用程序沒有能力去解決這一問題,通常情況下,JVM會做出終止線程的動作
(2) Exception —— 異常:異??梢苑譃檫\(yùn)行時異常和編譯期異常
RuntimeException:即運(yùn)行時異常,我們必須修正代碼
這些異常通常是由于一些邏輯錯誤產(chǎn)生的
這類異常在代碼編寫的時候不會被編譯器所檢測出來,是可以不需要被捕獲,但是程序員 也可以根據(jù)需要行捕獲拋出,(不受檢查異常)這類異常通常是可以被程序員避免的。
常見的RUNtimeException有:NullpointException(空指針異常),ClassCastException (類型轉(zhuǎn) 換異常),IndexOutOfBoundsException(數(shù)組越界異常)等。
非RuntimeException:編譯期異常,必須處理,否則程序編譯無法通過
這類異常在編譯時編譯器會提示需要捕獲,如果不進(jìn)行捕獲則編譯錯誤。
常見編譯異常有:IOException(流傳輸異常),SQLException(數(shù)據(jù)庫操作異常)等。
Java內(nèi)置異常類A:Java 的非檢查性異常
異常 | 描述 |
---|---|
ArithmeticException | 當(dāng)出現(xiàn)異常的運(yùn)算條件時,拋出此異常。例如,一個整數(shù)"除以零"時,拋出此類的一個實例。 |
ClassCastException | 拋出表示代碼嘗試將對象轉(zhuǎn)換為不屬于實例的子類。 例如:將Integer型對象轉(zhuǎn)換為String類 |
IllegalArgumentException | 拋出的異常表明向方法傳遞了一個不合法或不正確的參數(shù)。 |
NumberFormatException | 拋出以表示應(yīng)用程序已嘗試將字符串轉(zhuǎn)換為其中一個數(shù)字類型,但該字符串不具有相應(yīng)的格式。 |
IllegalStateException | 表示在非法或不適當(dāng)?shù)臅r間調(diào)用了一種方法。 換句話說,Java環(huán)境或Java應(yīng)用程序?qū)τ谡埱蟮牟僮鞑⒉惶幱谶m當(dāng)?shù)臓顟B(tài)。 |
IndexOutOfBoundsException | 指示某排序索引(例如對數(shù)組、字符串或向量的排序)超出范圍時拋出。 應(yīng)用程序可以將此類子類化以指示類似的異常。 |
ArrayIndexOutOfBoundsException | 用非法索引訪問數(shù)組時拋出的異常。如果索引為負(fù)或大于等于數(shù)組大小,則該索引為非法索引。 |
NoSuchElementException | 被各種訪問器方法拋出,表示被請求的元素不存在。 |
InputMismatchException | 輸入類型不匹配異常,一般出現(xiàn)此類異常的原因就是定義的接受輸入值的變量的類型與輸入的數(shù)值的類型不匹配導(dǎo)致的異常。 |
NullPointerException | 空指針異常 |
B:Java的檢查性異常
異常 | 描述 |
---|---|
ClassNotFoundException | 應(yīng)用程序試圖加載類時,找不到相應(yīng)的類,拋出該異常。 |
CloneNotSupportedException | 當(dāng)調(diào)用?Object?類中的?clone?方法克隆對象,但該對象的類無法實現(xiàn)?Cloneable?接口時,拋出該異常。 |
InstantiationException | 當(dāng)試圖使用?Class?類中的?newInstance?方法創(chuàng)建一個類的實例,而指定的類對象因為是一個接口或是一個抽象類而無法實例化時,拋出該異常。 |
A:捕獲單個異常
try{ //程序代碼 }catch (ExceptionName e1){ //Catch塊 }
B:多重捕獲塊
try{ //程序代碼 }catch (異常類型1 異常的變量名1){ ...... }catch (異常類型2 異常的變量名2){ ...... }catch (異常類型3 異常的變量名3){ ...... }
try:用于監(jiān)聽異常
catch:用于捕獲處理異常
try 后面的一對大括號內(nèi)的內(nèi)容即受到監(jiān)控的程序,也就是說這一段代碼是可能存在異常的,而Catch中由開發(fā)者,根據(jù)自身推斷可能存在的異常,書寫對應(yīng)異常類型以及處理方式,當(dāng)程序發(fā)生異常時,會創(chuàng)建異常對象,并且將異常拋出到此環(huán)境外,Java運(yùn)行時系統(tǒng)會尋找與發(fā)生異常所匹配的catch子句,當(dāng)找到一個對應(yīng)語句后則不再尋找其他catch塊
public class Demo { public static void main(String[] args) { int a = 520; int b = 0; int c; try { System.out.println("這是一個被除數(shù)為0的式子"); c = a / b; } catch (ArithmeticException e) { System.out.println("除數(shù)不能為0"); } } } //運(yùn)行結(jié)果 這是一個被除數(shù)為0的式子 除數(shù)不能為0
通過上例可以看到,被監(jiān)控的語句中先依次正常執(zhí)行,當(dāng)遇到存在問題的語句時,找到匹配異常,并且執(zhí)行catch塊中的語句
而一般來說我們會在catch語句塊中通過異常對象執(zhí)行異常方法
方法方法 | 說明 |
---|---|
public String getMessage() | 回關(guān)于發(fā)生的異常的詳細(xì)信息。這個消息在Throwable 類的構(gòu)造函數(shù)中初始化了 |
public Throwable getCause() | 返回一個Throwable 對象代表異常原因 |
public String toString() | 使用getMessage()的結(jié)果返回類的串級名字 |
public void printStackTrace() | 打印toString()結(jié)果和棧層次到System.err,即錯誤輸出流 |
我們還是用上面的例子給出異常方法的測試
System.out.println(e.getMessage()); / by zero
System.out.println(e.getCause()); null
System.out.println(e.toString()); java.lang.ArithmeticException: / by zero
e.printStackTrace(); java.lang.ArithmeticException: / by zero at cn.bwh_01_Throwable.Demo.main(Demo.java:10)(2) try-catch-finally
我們在 try-catch的基礎(chǔ)上再補(bǔ)充一個finally的知識
finally 關(guān)鍵字用來創(chuàng)建在 try 代碼塊后面執(zhí)行的代碼塊無論是否發(fā)生異常,finally 代碼塊中的代碼總會被執(zhí)行,在 finally 代碼塊中,可以運(yùn)行清理類型等收尾善后性質(zhì)的語句,finally 代碼塊出現(xiàn)在 catch 代碼塊最后,語法如下:
try{ ...... }catch(異常類型1 異常的變量名1){ ...... }catch(異常類型2 異常的變量名2){ ...... }finally{ ...... }
無論是否發(fā)生異常,fianlly始終都是會運(yùn)行的
這里就不得不提一個非常重要的注意點,那就是當(dāng)return遇到finally!
注意點我們來看下面一個例程:
public class Demo2 { public static void main(String[] args) { System.out.println(test()); } public static String test(){ int[] array = new int[2]; try{ array[3] = 0; return "This is try"; }catch (ArrayIndexOutOfBoundsException e){ System.out.println(e); return "This is catch 1"; }catch (Exception e){ System.out.println(e); return "This is catch 2"; }finally { System.out.println("This is finally"); //return "This is finally"s return"; } } } //運(yùn)行結(jié)果 java.lang.ArrayIndexOutOfBoundsException: 3 This is finally This is catch 1
由此我們得出一個結(jié)論:在catch中遇到return時,仍然會先執(zhí)行finally語句,再回來執(zhí)行對應(yīng)catch語句中的return語句
但是我們?nèi)绻麑inally中return行中的注釋去掉,運(yùn)行結(jié)果就會變成下面這樣子
//運(yùn)行結(jié)果 java.lang.ArrayIndexOutOfBoundsException: 3 This is finally This is finally"s return
結(jié)果就是返回值會被finally中的return語句重新覆蓋
public class Demo3 { public static void main(String[] args) { int[] array = new int[2]; try{ array[5] = 0; }catch (Exception e){ }catch (ArrayIndexOutOfBoundsException e){ } } } //運(yùn)行結(jié)果 Error:(8, 10) java: 已捕獲到異常錯誤java.lang.ArrayIndexOutOfBoundsException
對于多個catch的情況,當(dāng)try中程序發(fā)生異常,會按照從上往下的順序與catch進(jìn)行匹配,一旦與其中一個匹配后就不會再與后面的catch進(jìn)行匹配了,所以,在書寫catch語句的時候,一定要把范圍小的放在前面,范圍大的放在后面!
(3) throw/throws將自己處理不了的,在方法或者語句上聲明,告訴調(diào)用者,這里有問題
如果一個方法沒有捕獲到檢查性異常,那么該方法就必須使用throws關(guān)鍵字聲明(聲明拋出多個異常,之間使用逗號隔開),也可以在語句中使用throw關(guān)鍵字拋出一個異常。
//演示throw public class Demo4 { public static void main(String[] args) { test(); } public static void test() { int a = 520; int b = 0; if (b == 0) { throw new ArithmeticException(); } else { System.out.println(a / b); } } } //運(yùn)行結(jié)果 Exception in thread "main" java.lang.ArithmeticException
//演示throws public class Demo4 { public static void main(String[] args) { try { test(); } catch (Exception e) { e.printStackTrace(); } } public static void test() throws Exception { int a = 520; int b = 0; if (b == 0) { throw new Exception(); } else { System.out.println(a / b); } } } //運(yùn)行結(jié)果 java.lang.Exception
A:throws
用在方法聲明后,跟的是異常類名
可以跟多個異常類名,用逗號隔開
表示拋出異常,由該方法的調(diào)用者來處理
throws表示出現(xiàn)異常的一種可能性,不一定會發(fā)生這些異常
B:throw
用在方法體內(nèi),跟的是異常對象名
只能拋出一個異常對象名
表示拋出異常,由方法體內(nèi)的語句處理
執(zhí)行throw則一定拋出了某種異常
(三) 自定義異常Java內(nèi)置的異常類,基本可以滿足我們在編程中遇到的大部分異常情況,此外我們還可以自定義異常類,只需要繼承Exception類即可
基本步驟:
創(chuàng)建自定義異常類
在方法中通過throw拋出異常對象
在當(dāng)前拋出異常的方法中處理異常,可以使用try-catch語句捕獲處理
也可以在方法聲明處使用throws將異常拋給方法調(diào)用者
在出現(xiàn)異常方法的調(diào)用者中捕獲并且處理異常
class MyException extends Exception { // 自定義的類 MyException(String s) { super(s); } } class Demo { void method() throws MyException { throw new MyException("Wrong"); // 拋出自定義的類 } } class DemoTest { public static void main(String[] args){ try { new Demo().method(); } catch(MyException e) { System.out.println(e.getMessage()); } } } //運(yùn)行結(jié)果 Wrong(三) 總結(jié)
異常就是在程序發(fā)生異常時,強(qiáng)制終止程序運(yùn)行,并且將異常信息返回,由開發(fā)者決定是否處理異常
簡單說一下這個異常機(jī)制的過程:
當(dāng)程序無法運(yùn)行后,它會從當(dāng)前環(huán)境中跳出,并且拋出異常,之后,它會先new一個異常對象,然后在異常位置終止程序,并且將異常對象的引用從當(dāng)前環(huán)境中返回,這時候異常處理機(jī)制接管程序,并且開始尋找可以繼續(xù)執(zhí)行程序的恰當(dāng)位置。
結(jié)尾:如果內(nèi)容中有什么不足,或者錯誤的地方,歡迎大家給我留言提出意見, 蟹蟹大家 !^_^
如果能幫到你的話,那就來關(guān)注我吧?。ㄏ盗形恼戮鶗诠娞柕谝粫r間更新)
在這里的我們素不相識,卻都在為了自己的夢而努力 ?一個堅持推送原創(chuàng)Java技術(shù)的公眾號:理想二旬不止
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/75312.html
摘要:另外一種方法是,將這個線程加入一個線程組,在線程組里重寫方法來處理拋出的異常,這時線程組的作用相當(dāng)于實現(xiàn)了的類。使用對象處理異常格式錯誤使用線程組處理異常測試異常 感性地理解一下什么是線程? 線程這個概念其實是比較抽象的,雖然依照教科書上的說法: 進(jìn)程是從系統(tǒng)獲取資源的最小單位,線程是程序執(zhí)行的最小單位。程序是靜態(tài)存在于磁盤上的一段文本,進(jìn)程運(yùn)行這段文本記錄的命令。 也就是說,進(jìn)程從系...
摘要:實踐很簡單的一個類,點開它的源代碼,其中所有的方法都是與相關(guān)聯(lián)的。從而很好地避免了空指針異常。方法,如果存在,返回包含的值,否則拋出異常。隨便點開一個方法,都會在第一行為不該為的參數(shù)進(jìn)行判斷。 問題描述 在大熱的Spring Boot 2.0中,在將原來的泛型改為了Optional,旨在讓我們的代碼更簡潔。 showImg(https://segmentfault.com/img/bV...
摘要:是指可能導(dǎo)致程序終止的非常嚴(yán)重的時間。具有最高的級別,旨在關(guān)閉中的日志功能。因此為每一個消息選擇一個合適的日志級別是非常重要的。日志的個小建議將日志訪日代碼塊它能顯著的減少因為字符串拼接而帶來的性能的影響。 前言 首先,這篇文章沒有進(jìn)行任何的日志功能的詳細(xì)介紹,而是對日志提出了幾種最佳實踐。適合對日志記錄有所了解的同學(xué)閱讀。下面是正文: JAVA日志管理既是一門科學(xué),又是一門藝術(shù)??茖W(xué)...
閱讀 1034·2023-04-25 22:27
閱讀 880·2021-11-22 14:56
閱讀 996·2021-11-11 16:54
閱讀 1695·2019-08-30 15:54
閱讀 3512·2019-08-30 13:20
閱讀 1220·2019-08-30 10:55
閱讀 2091·2019-08-26 13:34
閱讀 3291·2019-08-26 11:53