異常
1. Throwable: 有兩個(gè)重要的子類:Exception(異常)和Error(錯(cuò)誤)
2. Error: 程序無法處理的錯(cuò)誤捂齐。大多數(shù)錯(cuò)誤與代碼編寫者執(zhí)行的操作無關(guān)确徙,而表示代碼運(yùn)行時(shí)JVM出現(xiàn)的問題,例如乎莉,Java虛擬機(jī)運(yùn)行錯(cuò)誤(Virtual MachineError)愚屁,當(dāng) JVM 不再有繼續(xù)執(zhí)行操作所需的內(nèi)存資源時(shí),將出現(xiàn) OutOfMemoryError絮重。這些異常發(fā)生時(shí)冤寿,Java虛擬機(jī)(JVM)一般會(huì)選擇線程終止。
3. Exception: 是程序本身可以處理的異常
-
RuntimeException
表示JVM常用操作引發(fā)的錯(cuò)誤青伤,例如督怜,若試圖使用空值對(duì)象引用、除數(shù)為零或數(shù)組越界狠角,則分別引發(fā)運(yùn)行時(shí)異常(NullPointerException号杠、ArithmeticException)和 ArrayIndexOutOfBoundException。注意:異常和錯(cuò)誤的區(qū)別:異常能被程序本身可以處理丰歌,錯(cuò)誤是無法處理姨蟋。
-
JAVA異常(包括Exception和Error)分為可查的異常(checked exceptions)和不可查的異常(unchecked exceptions)。
可查異常
除了RuntimeException及其子類以外动遭,其他的Exception類及其子類都屬于可查異常芬探。要么用try-catch語句捕獲它,要么用throws子句聲明拋出它厘惦,否則編譯不會(huì)通過偷仿。不可查異常:包括運(yùn)行時(shí)異常(RuntimeException與其子類)和錯(cuò)誤(Error)。
-
Exception 這種異常分兩大類運(yùn)行時(shí)異常和非運(yùn)行時(shí)異常(編譯異常)宵蕉。
-
運(yùn)行時(shí)異常
RuntimeException類及其子類異常酝静,如NullPointerException(空指針異常)、IndexOutOfBoundsException(下標(biāo)越界異常)等羡玛,這些異常是不檢查異常别智,程序中可以選擇捕獲處理,也可以不處理稼稿。運(yùn)行時(shí)異常特點(diǎn):Java編譯器不會(huì)檢查它薄榛,也就是說,當(dāng)程序中可能出現(xiàn)這類異常让歼,即使沒有用try-catch語句捕獲它敞恋,也沒有用throws子句聲明拋出它,也會(huì)編譯通過谋右。
非運(yùn)行時(shí)異常(編譯異常)
是RuntimeException以外的異常硬猫,類型上都屬于Exception類及其子類。必須進(jìn)行處理的異常,如果不處理啸蜜,程序就不能編譯通過坑雅。如IOException、SQLException等以及用戶自定義的Exception異常
-
異常處理機(jī)制
總體來說:對(duì)于可查異常必須捕捉衬横、或者聲明拋出裹粤。允許忽略不可查的 RuntimeException 和 Error。
捕獲異常:try冕香、catch 和 finally
1. try-catch語句
語法:
try {
// 可能會(huì)發(fā)生異常的程序代碼
} catch (Type1 id1){
// 捕獲并處置try拋出的異常類型Type1
}
catch (Type2 id2){
//捕獲并處置try拋出的異常類型Type2
}
try后為監(jiān)控區(qū)域蛹尝。若出現(xiàn)異常,則創(chuàng)建異常對(duì)象悉尾,將對(duì)象拋出監(jiān)控區(qū)域之外并尋找匹配的catch子句捕獲異常。
匹配原則:若拋出對(duì)象屬于catch句子的異常類或子類挫酿,則匹配例1 “除數(shù)為0”引發(fā)的ArithmeticException異常构眯。
public static void main(String[] args) {
int a = 6;
int b = 0;
try {
System.out.println("a/b的值是:" + a / b);
} catch (ArithmeticException e) {
System.out.println("程序出現(xiàn)異常,變量b不能為0早龟。");
}
System.out.println("程序正常結(jié)束惫霸。");
}
}
結(jié)果:
程序出現(xiàn)異常,變量b不能為0葱弟。
程序正常結(jié)束壹店。
在該例中,b=0引發(fā)ArithmeticException異常芝加,運(yùn)行時(shí)系統(tǒng)創(chuàng)建異常對(duì)象并拋出監(jiān)控區(qū)域硅卢,轉(zhuǎn)而匹配合適的異常處理器catch,并執(zhí)行相應(yīng)的異常處理代碼藏杖。
事實(shí)上将塑,ArithmeticException異常屬于運(yùn)行時(shí)異常,由于檢查運(yùn)行時(shí)異常的代價(jià)遠(yuǎn)大于捕捉異常所帶來的益處蝌麸,所以一般不做處理例2 存在除數(shù)為0和下標(biāo)越界異常
public class TestException {
public static void main(String[] args) {
int[] intArray = new int[3];
try {
for (int i = 0; i <= intArray.length; i++) {
intArray[i] = i;
System.out.println("intArray[" + i + "] = " + intArray[i]);
System.out.println("intArray[" + i + "]模 " + (i - 2) + "的值: "
+ intArray[i] % (i - 2));
}
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("intArray數(shù)組下標(biāo)越界異常点寥。");
} catch (ArithmeticException e) {
System.out.println("除數(shù)為0異常。");
}
System.out.println("程序正常結(jié)束来吩。");
}
}
結(jié)果:
intArray[0] = 0
intArray[0]模 -2的值: 0
intArray[1] = 1
intArray[1]模 -1的值: 0
intArray[2] = 2
除數(shù)為0異常敢辩。
程序正常結(jié)束。
-
在該例中弟疆,可能會(huì)出現(xiàn)下標(biāo)越界和除數(shù)為0兩種異常戚长,但除數(shù)為0先匹配,因此執(zhí)行相應(yīng)的catch語句
注意:一旦某個(gè)catch捕獲到匹配的異常類型兽间,將進(jìn)入異常處理代碼历葛。一經(jīng)處理結(jié)束,就意味著整個(gè)try-catch語句結(jié)束。其他的catch子句不再有匹配和捕獲異常類型的機(jī)會(huì)
2. try-catch-finally 語句
語法:
try {
// 可能會(huì)發(fā)生異常的程序代碼
} catch (Type1 id1) {
// 捕獲并處理try拋出的異常類型Type1
} catch (Type2 id2) {
// 捕獲并處理try拋出的異常類型Type2
} finally {
// 無論是否發(fā)生異常恤溶,都將執(zhí)行的語句塊
}
- 例1 帶finally子句的異常處理程序乓诽。
public class TestException {
public static void main(String args[]) {
int i = 0;
String greetings[] = { " Hello world !", " Hello World !! "};
while (i < 3) {
try {
// 特別注意循環(huán)控制變量i的設(shè)計(jì),避免造成無限循環(huán)
System.out.println(greetings[i++]);
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("數(shù)組下標(biāo)越界異常");
} finally {
System.out.println("--------------------------");
}
}
}
}
運(yùn)行結(jié)果:
Hello world !
--------------------------
Hello World !!
--------------------------
數(shù)組下標(biāo)越界異常
--------------------------
- 特別注意try子句中語句塊的設(shè)計(jì)咒程,如果設(shè)計(jì)為如下鸠天,將會(huì)出現(xiàn)死循環(huán)。
try { System.out.println (greetings[i]); i++; }
小結(jié):
try 塊:用于捕獲異常帐姻。其后可接零個(gè)或多個(gè)catch塊稠集,如果沒有catch塊,則必須跟一個(gè)finally塊饥瓷。
catch 塊:用于處理try捕獲到的異常剥纷。
finally 塊:無論是否捕獲或處理異常,finally塊里的語句都會(huì)被執(zhí)行呢铆。當(dāng)在try塊或catch塊中遇到return語句時(shí)晦鞋,finally語句塊將在方法返回之前被執(zhí)行。在以下4種特殊情況下棺克,finally塊不會(huì)被執(zhí)行:
1)在finally語句塊中發(fā)生了異常悠垛。
2)在前面的代碼中用了System.exit()退出程序。
3)程序所在的線程死亡娜谊。
4)關(guān)閉CPU确买。
3. try、catch纱皆、finally語句塊的執(zhí)行順序
1)try中沒有異常:try中順序執(zhí)行湾趾,跳過catch語句,執(zhí)行finally語句和后面的語句
2)try捕獲異常抹剩,沒有catch匹配異常:該異常會(huì)拋給JVM處理撑帖,finally語句塊還是會(huì)執(zhí)行,但后面的語句不會(huì)執(zhí)行
3)try捕獲異常澳眷,有catch匹配并處理:出現(xiàn)異常胡嘿,程序跳到相應(yīng)的catch語句塊,其他catch不會(huì)執(zhí)行钳踊,try語句塊中衷敌,出現(xiàn)異常之后的語句也不會(huì)被執(zhí)行,catch執(zhí)行完之后執(zhí)行finally語句塊拓瞪,最后執(zhí)行后面的語句
拋出異常
1. throws拋出異常
語法:
methodname throws Exception1,Exception2,...
{
}
- throws語句在定義方法時(shí)聲明要拋出的異常類型缴罗,多個(gè)異常可以用逗號(hào)分隔祭埂。當(dāng)方法拋出異常時(shí)面氓,該方法不對(duì)這些類型的異常以及子類進(jìn)行處理兵钮,而是拋向調(diào)用該方法的方法。例如:
import java.lang.Exception;
public class Test {
static void pop() throws NegativeArraySizeException {
// 定義方法并拋出NegativeArraySizeException異常
int[] arr = new int[-3]; // 創(chuàng)建數(shù)組
}
public static void main(String[] args) { // 主方法
try { // try語句處理異常信息
pop(); // 調(diào)用pop()方法
} catch (NegativeArraySizeException e) {
System.out.println("pop()方法拋出的異常");// 輸出異常信息
}
}
}
使用throws關(guān)鍵字將異常拋給調(diào)用者后舌界,如果調(diào)用者不想處理該異常掘譬,可以繼續(xù)向上拋出,但最終要有能夠處理該異常的調(diào)用者呻拌。
pop方法沒有處理異常NegativeArraySizeException葱轩,而是由main函數(shù)來處理。throws拋出異常規(guī)則
1)不可查異常(Error藐握,RuntimeException)靴拱,可以不拋出,編譯時(shí)會(huì)通過猾普,運(yùn)行時(shí)被系統(tǒng)拋出
2)可查異常袜炕,要么拋出,要么捕獲
3)當(dāng)拋出異常抬闷,該方法的調(diào)用者必須處理或者重新拋出
4)若聲明一個(gè)異常妇蛀,則不能聲明與覆蓋方法不同的異常。聲明的任何異常必須是被覆蓋方法所聲明異常的同類或子類笤成。
例如:
void method1() throws IOException{} //合法
//編譯錯(cuò)誤,必須捕獲或聲明拋出IOException
void method2(){
method1();
}
//合法眷茁,聲明拋出IOException
void method3()throws IOException {
method1();
}
//合法炕泳,聲明拋出Exception,IOException是Exception的子類
void method4()throws Exception {
method1();
}
//合法上祈,捕獲IOException
void method5(){
try{
method1();
}catch(IOException e){…}
}
//編譯錯(cuò)誤培遵,必須捕獲或聲明拋出Exception
void method6(){
try{
method1();
}catch(IOException e){throw new Exception();}
}
//合法,聲明拋出Exception
void method7()throws Exception{
try{
method1();
}catch(IOException e){throw new Exception();}
}
2. 使用throws
throw用來拋出一個(gè)Throwable類型的異常登刺。程序會(huì)在throw語句后立即終止籽腕,它后面的語句執(zhí)行不到,然后在包含它的所有try塊中(可能在上層調(diào)用函數(shù)中)從里向外尋找含有與其匹配的catch子句的try塊纸俭。
-
異常是異常類的實(shí)例對(duì)象皇耗,我們可以創(chuàng)建異常類的實(shí)例對(duì)象通過throw語句拋出。該語句的語法格式為:
throw new exceptionname;
例如拋出一個(gè)IOException類的異常對(duì)象:
throw new IOException;
-
注意的是揍很,throw 拋出的只能夠是Throwable類 或者其子類的實(shí)例對(duì)象郎楼。下面的操作是錯(cuò)誤的:
throw new String("exception");
如果拋出了檢查異常,則還應(yīng)該在方法頭部聲明方法可能拋出的異常類型窒悔。該方法的調(diào)用者也必須檢查處理拋出的異常呜袁。
如果所有方法都層層上拋獲取的異常,最終JVM會(huì)進(jìn)行處理简珠,處理也很簡(jiǎn)單阶界,就是打印異常消息和堆棧信息。如果拋出的是Error或RuntimeException,則該方法的調(diào)用者可選擇處理該異常膘融。
package Test;
import java.lang.Exception;
public class TestException {
static int quotient(int x, int y) throws MyException { // 定義方法拋出異常
if (y < 0) { // 判斷參數(shù)是否小于0
throw new MyException("除數(shù)不能是負(fù)數(shù)"); // 異常信息
}
return x/y; // 返回值
}
public static void main(String args[]) { // 主方法
int a =3;
int b =0;
try { // try語句包含可能發(fā)生異常的語句
int result = quotient(a, b); // 調(diào)用方法quotient()
} catch (MyException e) { // 處理自定義異常
System.out.println(e.getMessage()); // 輸出異常信息
} catch (ArithmeticException e) { // 處理ArithmeticException異常
System.out.println("除數(shù)不能為0"); // 輸出提示信息
} catch (Exception e) { // 處理其他異常
System.out.println("程序發(fā)生了其他的異常"); // 輸出提示信息
}
}
}
class MyException extends Exception { // 創(chuàng)建自定義異常類
String message; // 定義String類型變量
public MyException(String ErrorMessagr) { // 父類方法
message = ErrorMessagr;
}
public String getMessage() { // 覆蓋getMessage()方法
return message;
}
}
JAVA常見異常
1. runtimeException子類
java.lang.ArrayIndexOutOfBoundsException
數(shù)組索引越界異常芙粱。當(dāng)對(duì)數(shù)組的索引值為負(fù)數(shù)或大于等于數(shù)組大小時(shí)拋出。java.lang.ArithmeticException
算術(shù)條件異常托启。譬如:整數(shù)除零等宅倒。java.lang.NullPointerException
空指針異常。當(dāng)應(yīng)用試圖在要求使用對(duì)象的地方使用了null時(shí)屯耸,拋出該異常拐迁。譬如:調(diào)用null對(duì)象的實(shí)例方法、訪問null對(duì)象的屬性疗绣、計(jì)算null對(duì)象的長(zhǎng)度线召、使用throw語句拋出null等等java.lang.ClassNotFoundException
找不到類異常。當(dāng)應(yīng)用試圖根據(jù)字符串形式的類名構(gòu)造類多矮,而在遍歷CLASSPAH之后找不到對(duì)應(yīng)名稱的class文件時(shí)缓淹,拋出該異常。java.lang.NegativeArraySizeException
數(shù)組長(zhǎng)度為負(fù)異常java.lang.ArrayStoreException
數(shù)組中包含不兼容的值拋出的異常java.lang.SecurityException
安全性異常java.lang.IllegalArgumentException
非法參數(shù)異常
2. IoException子類
- IOException:操作輸入流和輸出流時(shí)可能出現(xiàn)的異常塔逃。
- EOFException 文件已結(jié)束異常
- FileNotFoundException 文件未找到異常