複習17:異常Exception

異常

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拋出的異常

  1. 拋出
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("文件未找到");
	}
}

  1. 方法內處理
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的執行分爲兩部分:

  1. 第一次執行到return:將結果保存到緩衝區,不直接返回
  2. 監測到所有代碼執行完畢:將緩衝區中的結果返回,結束方法

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
	}
	 
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章