異常
Exception是什麼
- 概念:程序中出現的各種異常的總稱
- 具體:Java中所有異常類的父類
Exception與Error的區別
- Exception:不正常的事情,但是可以解決
- Error:不可以解決,或者解決起來非常麻煩
Exception的分類
未檢查異常(又叫運行時異常)
-
父類:RuntimeException(RuntimeException的父類也是Exception)
-
解釋:編輯器未報錯,程序運行時被拋出的異常。
-
產生:由程序員馬虎引起的異常,屬於程序員意料之外的異常。例如空指針異常,數組越界異常。
-
解決:該異常不要求程序員做相關預防措施,只需要更正代碼即可
-
示例:
- NullPointerException
- ArrayIndexOutOfBoundException
- StringIndexOutOfBoundException
- ClassCastException
- EOFException
- CurrentModifyException
程序遇到運行時異常時會立即結束,不會繼續運行之後的代碼
已檢查異常
-
父類:Exception
-
解釋:編輯器報錯,編譯不通過。
-
產生:不是程序本身導致,有可能由外部因素引起。例如使用IO時發現指定文件不存在,則拋出FileNotFoundException
-
解決:該異常程序員無法解決,但是可以預測並作出相應預防措施,當異常發生時啓動預防措施
檢查的執行者是編輯器,編輯器沒檢查出來的異常叫未檢查異常,編輯器檢查出來的異常叫已檢查異常
處理已檢查異常的方式
try-catch(-finally)
在出現異常的方法中,捕獲並處理相關異常,可以處理未檢查異常。
try-catch相當於if-else
- try:正常情況下,執行try中的代碼。try必須存在,且只能有一個。
- catch:出現異常時,由catch抓取異常並執行相應catch中的代碼。catch必須存在,且可以有多個。
- finally:除了System.exit(0)之外的任何情況,finally中的代碼都會執行,所以通常用來執行關閉流、JDBC鏈接等釋放資源的操作。finally相當於try-catch的附加模塊,可以省略;如果寫了,那隻能存在一個。
注意:catch按照從上往下的順序進行抓取異常,有父子關係的異常應嚴格按照權限範圍的從小到大排列(子類在上,父類在下),因爲catch不會多次捕獲同一個異常,即一旦某個異常被catch捕獲過一次之後,下面的catch將不會繼續捕獲該異常;沒有父子關係的異常則可以隨意排序。
package day20191128;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
public class Demo01 {
public void T() {
method();
}
public void method() {
/**
*try、catch、finally是三個獨立的代碼塊,其中聲明的變量都是局部變量,無法互通
*/
try {
FileInputStream f = new FileInputStream("a.txt");
} catch (FileNotFoundException e) {
/**
* FileNotFoundException e:創建異常的實例對象
* printStackTrace():打印錯誤信息
* catch中的內容可自定義
*/
System.out.println("發生錯誤!");
e.printStackTrace();
}catch(IOException e){
/**
*IOEception是FileNotFoundException的父類,所以需要放在下面
*/
e.printStackTrace();
}catch(..){
}finally{
}
/**
* try-catch之後的代碼會正常運行
*/
System.out.println(1);
}
}
注意:異常點之後的代碼不會被執行;try-catch之後的代碼會正常運行
throws
在除主方法外的方法聲明上拋出方法,方法調用者處理被拋出異常(也可以選擇繼續向外拋出,但是最後一級調用者必須處理異常)。注意:throws可以同時拋出多個異常,用逗號分隔。
package day20191128;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
public class Demo02 {
public static void main(String[] args) {
Test t = new Test();
try {
t.method();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
class Test{
public void method() throws FileNotFoundException {
FileInputStream f = new FileInputStream("a.txt");
}
}
注意:throws之後的語句不會執行
throw
throw也是拋出異常的一種方式,與throws有以下區別
-
throws通常是編輯器強制要求拋出(異常必須存在),throw是程序員人爲地製造一個異常並拋出
-
throws在方法聲明中拋出異常,拋給方法調用者;throw在方法體內執行,拋給方法本身
-
throws拋出的是異常的名稱,throw拋出的是異常的實例對象
-
throws可以同時拋出多個異常,throw只能拋出一個
-
throws拋出的異常可能會發生也可能不會發生,throw的語句被執行說明異常必定發生
方法調用者也要處理被throw拋出的異常
- 拋出
package day20191128;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
public class Demo02 {
public static void main(String[] args) {
Test t = new Test();
try {
t.method();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class Test{
public void method() throws FileNotFoundException {
throw new java.io.FileNotFoundException("文件未找到");
}
}
- 方法內處理
package day20191128;
public class Demo02 {
public static void main(String[] args) {
Test t = new Test();
t.method();
}
}
class Test{
public void method() {
try {
throw new java.io.FileNotFoundException("文件未找到");
}catch(Exception e) {
e.printStackTrace();
}
}
}
注意:throw之後的語句同樣無法執行
關於finally的小擴展
代碼如下,問最終輸出結果是什麼?
package day20191128;
public class Demo03 {
public static void main(String[] args) {
Test t = new Test();
System.out.println(t.method());
System.out.println(t.a);
}
}
class Test{
int a = 18;
public int method() {
try {
int i = a/0;
return a;
}catch(Exception e) {
return a;
}finally {
a++;
}
}
}
答:以上代碼的最終輸出結果爲18,19。
分析:從答案中我們可以看出finally在catch的return之後執行,衆所周知,return的作用是返回結果並結束方法,然而結果卻與我們的認知相悖,這是爲什麼呢?這是由return的執行過程決定的,return的執行分爲兩部分:
- 第一次執行到return:將結果保存到緩衝區,不直接返回
- 監測到所有代碼執行完畢:將緩衝區中的結果返回,結束方法
finally的執行是在return的第一步之後、第二步之前,因爲return是返回緩衝區中的結果,所以a++影響不到方法返回值,最終得到了18,19的結果。
自定義異常
package day20191128;
/**
*
* @author DL
* 用戶名或密碼錯誤異常
* 已檢查異常:extends Exception
* 未檢查異常:extends RuntimeException
*/
public class IdOrPwdException extends Exception{
public IdOrPwdException() {
super("用戶名/密碼錯誤");
// TODO Auto-generated constructor stub
}
public IdOrPwdException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
// TODO Auto-generated constructor stub
}
public IdOrPwdException(String message, Throwable cause) {
super(message, cause);
// TODO Auto-generated constructor stub
}
public IdOrPwdException(String message) {
super(message);
// TODO Auto-generated constructor stub
}
public IdOrPwdException(Throwable cause) {
super(cause);
// TODO Auto-generated constructor stub
}
}