JVM 處理方式:
1.把異常的名稱,錯(cuò)誤原因及異常出現(xiàn)的位置等信息輸出在了控制臺(tái)
2.程序停止執(zhí)行
1.異常體系

2.編譯時(shí)異常和運(yùn)行時(shí)異常
-
編譯時(shí)異常
- 都是Exception類及其子類
- 必須顯示處理,否則程序就會(huì)發(fā)生錯(cuò)誤,無(wú)法通過(guò)編譯
-
運(yùn)行時(shí)異常
- 都是RuntimeException類及其子類
- 無(wú)需顯示處理,也可以和編譯時(shí)異常一樣處理

3:throws方式處理異常
-
定義格式
public void 方法() throws 異常類名 { } -
示例代碼
public class ExceptionDemo { public static void main(String[] args) throws ParseException{ System.out.println("開始"); // method(); method2(); System.out.println("結(jié)束"); } //編譯時(shí)異常 public static void method2() throws ParseException { String s = "2048-08-09"; SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); Date d = sdf.parse(s); System.out.println(d); } //運(yùn)行時(shí)異常 public static void method() throws ArrayIndexOutOfBoundsException { int[] arr = {1, 2, 3}; System.out.println(arr[3]); } }- 這個(gè)throws格式是跟在方法的括號(hào)后面的
- 編譯時(shí)異常必須要進(jìn)行處理,兩種處理方案:try...catch …或者 throws,如果采用 throws 這種方案,在方法上進(jìn)行顯示聲明,將來(lái)誰(shuí)調(diào)用這個(gè)方法誰(shuí)處理
- 運(yùn)行時(shí)異常因?yàn)樵谶\(yùn)行時(shí)才會(huì)發(fā)生,所以在方法后面可以不寫,運(yùn)行時(shí)出現(xiàn)異常默認(rèn)交給jvm處理
4:throw拋出異常
throw new 異常();
這個(gè)格式是在方法內(nèi)的,表示當(dāng)前代碼手動(dòng)拋出一個(gè)異常,下面的代碼不用再執(zhí)行了
-
throws和throw的區(qū)別
throws throw 用在方法聲明后面,跟的是異常類名 用在方法體內(nèi),跟的是異常對(duì)象名 表示聲明異常,調(diào)用該方法有可能會(huì)出現(xiàn)這樣的異常 表示手動(dòng)拋出異常對(duì)象,由方法體內(nèi)的語(yǔ)句處理 -
示例代碼
public class ExceptionDemo8 { public static void main(String[] args) { //int [] arr = {1,2,3,4,5}; int [] arr = null; printArr(arr);//就會(huì) 接收到一個(gè)異常. //我們還需要自己處理一下異常. } private static void printArr(int[] arr) { if(arr == null){ //調(diào)用者知道成功打印了嗎? //System.out.println("參數(shù)不能為null"); throw new NullPointerException(); //當(dāng)參數(shù)為null的時(shí)候 //手動(dòng)創(chuàng)建了一個(gè)異常對(duì)象,拋給了調(diào)用者,產(chǎn)生了一個(gè)異常 }else{ for (int i = 0; i < arr.length; i++) { System.out.println(arr[i]); } } } }
5 try-catch方式處理異常
-
定義格式
try { 可能出現(xiàn)異常的代碼; } catch(異常類名 變量名) { 異常的處理代碼; } -
執(zhí)行流程
- 程序從 try 里面的代碼開始執(zhí)行
- 出現(xiàn)異常,就會(huì)跳轉(zhuǎn)到對(duì)應(yīng)的 catch 里面去執(zhí)行
- 執(zhí)行完畢之后,程序還可以繼續(xù)往下執(zhí)行
-
示例代碼
public class ExceptionDemo01 { public static void main(String[] args) { System.out.println("開始"); method(); System.out.println("結(jié)束"); } public static void method() { try { int[] arr = {1, 2, 3}; System.out.println(arr[3]); System.out.println("這里能夠訪問(wèn)到嗎"); } catch (ArrayIndexOutOfBoundsException e) { System.out.println("你訪問(wèn)的數(shù)組索引不存在,請(qǐng)回去修改為正確的索引"); } } } -
注意
如果 try 中沒(méi)有遇到問(wèn)題,怎么執(zhí)行?
會(huì)把try中所有的代碼全部執(zhí)行完畢,不會(huì)執(zhí)行catch里面的代碼如果 try 中遇到了問(wèn)題,那么 try 下面的代碼還會(huì)執(zhí)行嗎?
那么直接跳轉(zhuǎn)到對(duì)應(yīng)的catch語(yǔ)句中,try下面的代碼就不會(huì)再執(zhí)行了
當(dāng)catch里面的語(yǔ)句全部執(zhí)行完畢,表示整個(gè)體系全部執(zhí)行完全,繼續(xù)執(zhí)行下面的代碼如果出現(xiàn)的問(wèn)題沒(méi)有被捕獲,那么程序如何運(yùn)行?
那么try...catch就相當(dāng)于沒(méi)有寫.那么也就是自己沒(méi)有處理.
默認(rèn)交給虛擬機(jī)處理.同時(shí)有可能出現(xiàn)多個(gè)異常怎么處理?
出現(xiàn)多個(gè)異常,那么就寫多個(gè)catch就可以了.
注意點(diǎn):如果多個(gè)異常之間存在子父類關(guān)系.那么父類一定要寫在下面
4.8 Throwable成員方法(應(yīng)用)
-
常用方法
方法名 說(shuō)明 public String getMessage() 返回此 throwable 的詳細(xì)消息字符串 public String toString() 返回此可拋出的簡(jiǎn)短描述 public void printStackTrace() 把異常的錯(cuò)誤信息輸出在控制臺(tái) 示例代碼
public static void main(String[] args) {
System.out.println("開始");
method();
System.out.println("結(jié)束");
}
public static void method() {
try {
int[] arr = {1, 2, 3};
System.out.println(arr[3]); //new ArrayIndexOutOfBoundsException();
System.out.println("這里能夠訪問(wèn)到嗎");
} catch (ArrayIndexOutOfBoundsException e) { //new ArrayIndexOutOfBoundsException();
// 返回此 throwable 的詳細(xì)消息字符串
System.out.println(e.getMessage());
// 返回此可拋出的簡(jiǎn)短描述
System.out.println(e.toString());
//把異常的錯(cuò)誤信息輸出在控制臺(tái)
e.printStackTrace();
}
}
9:自定義異常
-
實(shí)現(xiàn)步驟
- 定義異常類
- 寫繼承關(guān)系
- 提供空參構(gòu)造
- 提供帶參構(gòu)造
-
代碼實(shí)現(xiàn)
異常類
public class AgeOutOfBoundsException extends RuntimeException { public AgeOutOfBoundsException() { } public AgeOutOfBoundsException(String message) { super(message); } }學(xué)生類
public class Student { private String name; private int age; public Student() { } public Student(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { if(age >= 18 && age <= 25){ this.age = age; }else{ //如果Java中提供的異常不能滿足我們的需求,我們可以使用自定義的異常 throw new AgeOutOfBoundsException("年齡超出了范圍"); } } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + '}'; } }測(cè)試類
public class ExceptionDemo12 { public static void main(String[] args) { // 鍵盤錄入學(xué)生的姓名和年齡,其中年齡為 18 - 25歲, // 超出這個(gè)范圍是異常數(shù)據(jù)不能賦值.需要重新錄入,一直錄到正確為止。 Student s = new Student(); Scanner sc = new Scanner(System.in); System.out.println("請(qǐng)輸入姓名"); String name = sc.nextLine(); s.setName(name); while(true){ System.out.println("請(qǐng)輸入年齡"); String ageStr = sc.nextLine(); try { int age = Integer.parseInt(ageStr); s.setAge(age); break; } catch (NumberFormatException e) { System.out.println("請(qǐng)輸入一個(gè)整數(shù)"); continue; } catch (AgeOutOfBoundsException e) { System.out.println(e.toString()); System.out.println("請(qǐng)輸入一個(gè)符合范圍的年齡"); continue; } /*if(age >= 18 && age <=25){ s.setAge(age); break; }else{ System.out.println("請(qǐng)輸入符合要求的年齡"); continue; }*/ } System.out.println(s); } }
10:finally
用來(lái)創(chuàng)建在 try 代碼塊后面執(zhí)行的代碼塊。
無(wú)論是否發(fā)生異常,finally 代碼塊中的代碼總會(huì)被執(zhí)行。在 finally 代碼塊中,可以運(yùn)行清理類型等收尾善后性質(zhì)的語(yǔ)句
try{
// 程序代碼
}catch(異常類型1 異常的變量名1){
// 程序代碼
}catch(異常類型2 異常的變量名2){
// 程序代碼
}finally{
// 程序代碼
}
- 實(shí)例
public class ExcepTest{
public static void main(String args[]){
int a[] = new int[2];
try{
System.out.println("Access element three :" + a[3]);
}catch(ArrayIndexOutOfBoundsException e){
System.out.println("Exception thrown :" + e);
}
finally{
a[0] = 6;
System.out.println("First element value: " +a[0]);
System.out.println("The finally statement is executed");
}
}
}
- 注意
- catch 不能獨(dú)立于 try 存在。
- 在 try/catch 后面添加 finally 塊并非強(qiáng)制性要求的。
- try 代碼后不能既沒(méi) catch 塊也沒(méi) finally 塊。
- try, catch, finally 塊之間不能添加任何代碼。
11:try-with-resources
DK7 之后,Java 新增的 try-with-resource 語(yǔ)法糖來(lái)打開資源,并且可以在語(yǔ)句執(zhí)行完畢后確保每個(gè)資源都被自動(dòng)關(guān)閉 。
JDK7 之前所有被打開的系統(tǒng)資源,比如流、文件或者 Socket 連接等,都需要被開發(fā)者手動(dòng)關(guān)閉,否則將會(huì)造成資源泄露。
try (resource declaration) {
// 使用的資源
} catch (ExceptionType e1) {
// 異常塊
}
try 用于聲明和實(shí)例化資源,catch 用于處理關(guān)閉資源時(shí)可能引發(fā)的所有異常。
public class RunoobTest {
public static void main(String[] args) {
String line;
try(BufferedReader br = new BufferedReader(new FileReader("test.txt"))) {
while ((line = br.readLine()) != null) {
System.out.println("Line =>"+line);
}
} catch (IOException e) {
System.out.println("IOException in try block =>" + e.getMessage());
}
}
}
我們實(shí)例一個(gè) BufferedReader 對(duì)象從 test.txt 文件中讀取數(shù)據(jù)。
在 try-with-resources 語(yǔ)句中聲明和實(shí)例化 BufferedReader 對(duì)象,執(zhí)行完畢后實(shí)例資源,不需要考慮 try 語(yǔ)句是正常執(zhí)行還是拋出異常。
如果發(fā)生異常,可以使用 catch 來(lái)處理異常。