什么是Java異常
異常是一個(gè)事件,它發(fā)生在程序運(yùn)行期間济蝉,干擾了正常的指令流程。Java通 過(guò)API中Throwable類的眾多子類描述各種不同的異常。因而王滤,Java異常都是對(duì)象贺嫂,是Throwable子類的實(shí)例,描述了出現(xiàn)在一段編碼中的 錯(cuò)誤條件淑仆。當(dāng)條件生成時(shí)涝婉,錯(cuò)誤將引發(fā)異常。
Java異常
Java異常結(jié)構(gòu)圖
Throwable:Throwable 指定代碼中可用異常傳播機(jī)制通過(guò)Java 應(yīng)用程序傳輸?shù)娜魏螁?wèn)題的共性蔗怠。有兩個(gè)重要的子類:Exception(異常)和Error(錯(cuò)誤)墩弯,二者都是 Java 異常處理的重要子類,各自都包含大量子類寞射。
Error:程序無(wú)法處理的錯(cuò)誤渔工,表示運(yùn)行程序中較嚴(yán)重問(wèn)題。大多數(shù)錯(cuò)誤與Coder無(wú)關(guān)桥温,而表示代碼運(yùn)行時(shí)JVM出現(xiàn)的問(wèn)題引矩。
Exception:程序本身可以處理的異常。
區(qū)別:異常能被程序本身處理侵浸,錯(cuò)誤是無(wú)法處理旺韭。
運(yùn)行時(shí)異常:RuntimeException類及其子類異常,如NullPointerException掏觉、IndexOutBoundsException等区端,這些異常是不檢查異常,可以選擇捕獲處理澳腹,也可以不捕獲织盼。
運(yùn)行時(shí)異常的特點(diǎn)是Java編譯器不會(huì)檢查它,也就是說(shuō)酱塔,當(dāng)程序中可能出現(xiàn)這類異常沥邻,即使沒(méi)有用try-catch語(yǔ)句捕獲它,也沒(méi)有用throws子句聲明拋出它羊娃,也會(huì)編譯通過(guò)唐全。
非運(yùn)行時(shí)異常:是RuntimeException以外的異常,類型上都屬于Exception類及其子類蕊玷。從程序語(yǔ)法角度講是必須進(jìn)行處理的異常芦瘾,如果不處理,程序就不能編譯通過(guò)集畅。如IOException、SQLException等以及用戶自定義的Exception異常缅糟,一般情況下不自定義檢查異常挺智。
處理異常機(jī)制
拋出異常:當(dāng)一個(gè)方法出現(xiàn)錯(cuò)誤引發(fā)異常時(shí),方法創(chuàng)建異常對(duì)象并交付運(yùn)行時(shí)系統(tǒng),異常對(duì)象中包含了異常類型和異常出現(xiàn)時(shí)的程序狀態(tài)等異常信息赦颇。運(yùn)行時(shí)系統(tǒng)負(fù)責(zé)尋找處置異常的代碼并執(zhí)行二鳄。
捕獲異常:在方法拋出異常之后,運(yùn)行時(shí)系統(tǒng)將轉(zhuǎn)為尋找合適的異常處理器(exception handler)媒怯。潛在的異常處理器是異常發(fā)生時(shí)依次存留在調(diào)用棧中的方法的集合订讼。當(dāng)異常處理器所能處理的異常類型與方法拋出的異常類型相符時(shí),即為合適的異常處理器扇苞。運(yùn)行時(shí)系統(tǒng)從發(fā)生異常的方法開(kāi)始欺殿,依次回查調(diào)用棧中的方法,直至找到含有合適異常處理器的方法并執(zhí)行鳖敷。當(dāng)運(yùn)行時(shí)系統(tǒng)遍歷調(diào)用棧而未找到合適的異常處理器脖苏,則運(yùn)行時(shí)系統(tǒng)終止。同時(shí)定踱,意味著Java程序的終止棍潘。
總體來(lái)說(shuō):Java規(guī)定,對(duì)于可查異常必須捕獲崖媚、或者聲明拋出亦歉。允許忽略不可查的RuntimeException和Error。
捕獲異常
1畅哑、try-catch語(yǔ)句
關(guān)鍵詞try后的一對(duì)大括號(hào)將一塊可能發(fā)生異常的代碼包起來(lái)肴楷,稱為監(jiān)控區(qū)域。Java方法在運(yùn)行過(guò)程中出現(xiàn)異常敢课,則創(chuàng)建異常對(duì)象阶祭。將異常拋出監(jiān)控區(qū)域之外,由Java運(yùn)行時(shí)系統(tǒng)試圖尋找匹配的catch子句以捕獲異常直秆。若有匹配的catch子句濒募,則運(yùn)行其異常處理代碼,try-catch語(yǔ)句結(jié)束圾结。
匹配的原則是:如果拋出的異常對(duì)象屬于catch子句的異常類瑰剃,或者屬于該異常類的子類,則認(rèn)為生成的異常對(duì)象與catch塊捕獲的異常類型相匹配筝野。
需要注意的是晌姚,一旦某個(gè)catch捕獲到匹配的異常類型,將進(jìn)入異常處理代碼歇竟,就意味著整個(gè)try-catch語(yǔ)句結(jié)束挥唠。其他的catch子句不再有匹配和捕獲異常類型的機(jī)會(huì)。
2焕议、try-catch-finally語(yǔ)句
finally子句表示無(wú)論是否出現(xiàn)異常宝磨,都應(yīng)當(dāng)執(zhí)行的內(nèi)容。
階段小結(jié)
**try ****塊:**用于捕獲異常。其后可接零個(gè)或多個(gè)catch塊唤锉,如果沒(méi)有 catch塊世囊,則必須跟一個(gè)finally塊。
**catch ****塊:**用于處理try捕獲到的異常窿祥。
**finally ****塊:**無(wú)論是否捕獲或處理異常株憾,finally塊里的語(yǔ)句都會(huì)被執(zhí)行。當(dāng)在try塊或catch塊中遇到return語(yǔ)句時(shí)晒衩,finally語(yǔ)句塊將在方法返回之前被執(zhí)行嗤瞎。在以下4種特殊情況下,finally塊不會(huì)被執(zhí)行:
1)在finally語(yǔ)句塊中發(fā)生了異常浸遗。
2)在前面的代碼中用了System.exit()退出程序猫胁。
3)程序所在的線程死亡。
4)關(guān)閉CPU跛锌。
3. try-catch-finally 規(guī)則(異常處理語(yǔ)句的語(yǔ)法規(guī)則):
1) 必須在 try 之后添加 catch 或 finally 塊弃秆。try 塊后可同時(shí)接 catch 和 finally 塊,但至少有一個(gè)塊髓帽。
2) 必須遵循塊順序:若代碼同時(shí)使用 catch 和 finally 塊菠赚,則必須將 catch 塊放在 try 塊之后。
3) catch 塊與相應(yīng)的異常類的類型相關(guān)郑藏。
4) 一個(gè) try 塊可能有多個(gè) catch 塊衡查。若如此,則執(zhí)行第一個(gè)匹配塊必盖。即Java虛擬機(jī)會(huì)把實(shí)際拋出的異常對(duì)象依次和各個(gè)catch代碼塊聲明的異常類型匹配拌牲,如果異常對(duì)象為某個(gè)異常類型或其子類的實(shí)例,就執(zhí)行這個(gè)catch代碼塊歌粥,不會(huì)再執(zhí)行其他的 catch代碼塊
5) 可嵌套 try-catch-finally 結(jié)構(gòu)塌忽。
6) 在 try-catch-finally 結(jié)構(gòu)中,可重新拋出異常失驶。
7) 除了下列情況土居,總將執(zhí)行 finally 做為結(jié)束:
JVM 過(guò)早終止(調(diào)用 System.exit(int));
在 finally 塊中拋出一個(gè)未處理的異常嬉探;
計(jì)算機(jī)斷電擦耀、失火、或遭遇病毒攻擊涩堤。
4. try眷蜓、catch、finally語(yǔ)句塊的執(zhí)行順序:
1)當(dāng)try沒(méi)有捕獲到異常時(shí):try語(yǔ)句塊中的語(yǔ)句逐一被執(zhí)行胎围,程序?qū)⑻^(guò)catch語(yǔ)句塊吁系,執(zhí)行finally語(yǔ)句塊和其后的語(yǔ)句芹敌;
2)當(dāng)try捕獲到異常,catch語(yǔ)句塊里沒(méi)有處理此異常的情況:當(dāng)try語(yǔ)句塊里的某條語(yǔ)句出現(xiàn)異常時(shí)垮抗,而沒(méi)有處理此異常的catch語(yǔ)句塊時(shí),此異常將會(huì)拋給JVM處理碧聪,finally語(yǔ)句塊里的語(yǔ)句還是會(huì)被執(zhí)行冒版,但finally語(yǔ)句塊后的語(yǔ)句不會(huì)被執(zhí)行;
3)當(dāng)try捕獲到異常逞姿,catch語(yǔ)句塊里有處理此異常的情況:在try語(yǔ)句塊中是按照順序來(lái)執(zhí)行的辞嗡,當(dāng)執(zhí)行到某一條語(yǔ)句出現(xiàn)異常時(shí),程序?qū)⑻絚atch語(yǔ)句塊滞造,并與catch語(yǔ)句塊逐一匹配续室,找到與之對(duì)應(yīng)的處理程序,其他的catch語(yǔ)句塊將不會(huì)被執(zhí)行谒养,而try語(yǔ)句塊中挺狰,出現(xiàn)異常之后的語(yǔ)句也不會(huì)被執(zhí)行,catch語(yǔ)句塊執(zhí)行完后买窟,執(zhí)行finally語(yǔ)句塊里的語(yǔ)句丰泊,最后執(zhí)行finally語(yǔ)句塊后的語(yǔ)句;
拋出異常
1. throws拋出異常
如果一個(gè)方法可能會(huì)出現(xiàn)異常始绍,但沒(méi)有能力處理這種異常瞳购,可以在方法聲明處用throws子句來(lái)聲明拋出異常。
**Throws拋出異常的規(guī)則:**
1) 如果是不可查異常(unchecked exception)亏推,即Error学赛、RuntimeException或它們的子類,那么可以不使用throws關(guān)鍵字來(lái)聲明要拋出的異常吞杭,編譯仍能順利通過(guò)盏浇,但在運(yùn)行時(shí)會(huì)被系統(tǒng)拋出。
2)必須聲明方法可拋出的任何可查異常(checked exception)篇亭。即如果一個(gè)方法可能出現(xiàn)受可查異常缠捌,要么用try-catch語(yǔ)句捕獲,要么用throws子句聲明將它拋出译蒂,否則會(huì)導(dǎo)致編譯錯(cuò)誤
3)僅當(dāng)拋出了異常曼月,該方法的調(diào)用者才必須處理或者重新拋出該異常。當(dāng)方法的調(diào)用者無(wú)力處理該異常的時(shí)候柔昼,應(yīng)該繼續(xù)拋出哑芹,而不是囫圇吞棗。
4)調(diào)用方法必須遵循任何可查異常的處理和聲明規(guī)則捕透。若覆蓋一個(gè)方法聪姿,則不能聲明與覆蓋方法不同的異常碴萧。聲明的任何異常必須是被覆蓋方法所聲明異常的同類或子類。
2. throw拋出異常
throw總是出現(xiàn)在函數(shù)體中末购,用來(lái)拋出一個(gè)Throwable類型的異常破喻。程序會(huì)在throw語(yǔ)句后立即終止,它后面的語(yǔ)句執(zhí)行不到盟榴,然后在包含它的所有try塊中(可能在上層調(diào)用函數(shù)中)從里向外尋找含有與其匹配的catch子句的try塊曹质。
Throwable類中的常用方法:
getCause():返回拋出異常的原因。如果cause不存在或未知擎场,則返回null
getMessage():返回異常的消息信息
printStackTrace():對(duì)象的堆棧跟蹤輸出至錯(cuò)誤輸出流羽德,作為字段System.err的值
Java常見(jiàn)異常
在Java中提供了一些異常用來(lái)描述經(jīng)常發(fā)生的錯(cuò)誤,對(duì)于這些異常迅办,有的需要程序員進(jìn)行捕獲處理或聲明拋出宅静,有的是由Java虛擬機(jī)自動(dòng)進(jìn)行捕獲處理。Java中常見(jiàn)的異常類:
1. runtimeException子類:
1站欺、 java.lang.ArrayIndexOutOfBoundsException 數(shù)組索引越界異常姨夹。當(dāng) 對(duì)數(shù)組的索引值為負(fù)數(shù)或大于等于數(shù)組大小時(shí)拋出。
2镊绪、java.lang.ArithmeticException 算術(shù)條件異常匀伏。譬如:整數(shù)除零等。
3蝴韭、java.lang.NullPointerException 空指針異常够颠。當(dāng)應(yīng)用試圖在要求使用對(duì)象的地方使用了null時(shí),拋出該異常榄鉴。譬如:調(diào)用null對(duì)象的實(shí)例方法履磨、訪問(wèn)null對(duì)象的屬性、計(jì)算null對(duì)象的長(zhǎng)度庆尘、使用throw語(yǔ)句拋出null等等
4剃诅、java.lang.ClassNotFoundException 找不到類異常。當(dāng)應(yīng)用試圖根據(jù)字符串形式的類名構(gòu)造類驶忌,而在遍歷CLASSPAH之后找不到對(duì)應(yīng)名稱的class文件時(shí)矛辕,拋出該異常。
5付魔、java.lang.NegativeArraySizeException 數(shù)組長(zhǎng)度為負(fù)異常
6聊品、java.lang.ArrayStoreException 數(shù)組中包含不兼容的值拋出的異常
7、java.lang.SecurityException 安全性異常
8几苍、java.lang.IllegalArgumentException 非法參數(shù)異常
2.IOException
IOException:操作輸入流和輸出流時(shí)可能出現(xiàn)的異常翻屈。
EOFException 文件已結(jié)束異常
FileNotFoundException 文件未找到異常
3.** 其他**
ClassCastException 類型轉(zhuǎn)換異常類
ArrayStoreException 數(shù)組中包含不兼容的值拋出的異常
SQLException 操作數(shù)據(jù)庫(kù)異常類
NoSuchFieldException 字段未找到異常
NoSuchMethodException 方法未找到拋出的異常
NumberFormatException 字符串轉(zhuǎn)換為數(shù)字拋出的異常
StringIndexOutOfBoundsException 字符串索引超出范圍拋出的異常
IllegalAccessException 不允許訪問(wèn)某類異常
InstantiationException 當(dāng)應(yīng)用程序試圖使用Class類中的newInstance()方法創(chuàng)建一個(gè)類的實(shí)例,而指定的類對(duì)象無(wú)法被實(shí)例化時(shí)妻坝,拋出該異常
?