Java之異常處理

異常的定義

異常:在Java語言中,將程序執行中發生的不正常狀況稱爲「異常」。 (開發過程當中的語法錯誤和邏輯錯誤不是異常)java

1. 異常的體系結構

Java程序在執行過程當中所發生的異常事件可分爲兩類:程序員

  1. Error: Java虛擬機沒法解決的嚴重問題。如:JVM系統內部錯誤、資源耗盡等嚴重狀況。好比: StackOverflowError和OOM。通常不編寫針對性的代碼進行處理。
  2. Exception:其它因編程錯誤或偶然的外在因素致使的通常性問題,可使用針對性的代碼進行處理。例如:
    • 空指針訪問
    • 試圖讀取不存在的文件
    • 網絡鏈接中斷
    • 數組角標越界
異常的體系結構
 * java.lang.Throwable
 * 		|-----java.lang.Error:通常不編寫針對性的代碼進行處理。
 * 		|-----java.lang.Exception:能夠進行異常的處理
 * 			|------編譯時異常(checked)不會生成字節碼文件
 * 					|-----IOException
 * 						|-----FileNotFoundException
 * 					|-----ClassNotFoundException
 * 			|------運行時異常(unchecked,RuntimeException)
 * 					|-----NullPointerException//空指針異常
 * 					|-----ArrayIndexOutOfBoundsException//數組角標越界
 * 					|-----ClassCastException//類型轉化異常
 * 					|-----NumberFormatException//編碼格式異常
 * 					|-----InputMismatchException//輸入不匹配
 * 					|-----ArithmeticException//算術異常

java中異常類的繼承關係面試

image-20200403161431591

2. 按照異常發生的時間能夠分爲兩類

  1. 運行時異常:執行javac.exe命名時,可能出現的異常 是指編譯器不要求強制處置的異常。通常是指編程時的邏輯錯誤,是程序員應該積極避免其出現的異常。 java. lang. Runtime Exception類及它的子類都是運行時異常。 對於這類異常,能夠不做處理,由於這類異常很廣泛,若全處理可能會對程序的可讀性和運行效率產生影響
  2. 編譯時異常:執行java.exe命名時,出現的異常 是指編譯器要求必須處置的異常。即程序在運行時因爲外界因素形成的通常性異常。編譯器要求Java程序==必須捕獲或聲明全部編譯時異常== 對於這類異常,若是程序不處理,可能會帶來意想不到的結果。

image-20200403162029470

3.常見的異常類型

//******************如下是運行時異常***************************
	//ArithmeticException
	@Test
	public void test6(){
		int a = 10;
		int b = 0;
		System.out.println(a / b);
	}
	
	//InputMismatchException
	@Test
	public void test5(){
		Scanner scanner = new Scanner(System.in);
		int score = scanner.nextInt();
		System.out.println(score);
		
		scanner.close();
	}
	
	//NumberFormatException
	@Test
	public void test4(){
		
		String str = "123";
		str = "abc";
		int num = Integer.parseInt(str);	
	}
	
	//ClassCastException
	@Test
	public void test3(){
		Object obj = new Date();
		String str = (String)obj;
	}
	
	//IndexOutOfBoundsException
	@Test
	public void test2(){
		//ArrayIndexOutOfBoundsException
//		int[] arr = new int[10];
//		System.out.println(arr[10]);
		//StringIndexOutOfBoundsException
		String str = "abc";
		System.out.println(str.charAt(3));
	}
	
	//NullPointerException
	@Test
	public void test1(){		
//		int[] arr = null;
//		System.out.println(arr[3]);
		
		String str = "abc";
		str = null;
		System.out.println(str.charAt(0));
		
	}

	//******************如下是編譯時異常***************************
	@Test
	public void test7(){
//		File file = new File("hello.txt");
//		FileInputStream fis = new FileInputStream(file);
//		
//		int data = fis.read();
//		while(data != -1){
//			System.out.print((char)data);
//			data = fis.read();
//		}
//		
//		fis.close();
		
	}

異常的處理

1. java異常處理的抓拋模型

過程一:"拋":程序在正常執行的過程當中,一旦出現異常,就會在異常代碼處生成一個對應異常類的對象。並將此對象拋出。一旦拋出對象之後,其後的代碼就再也不執行。數據庫

關於異常對象的產生:編程

① 系統自動生成的異常對象數組

② 手動的生成一個異常對象,並拋出(throw)網絡

過程二:"抓":能夠理解爲異常的處理方式:① try-catch-finally ② throwside

2.異常處理方式一:try-catch-finally

2.1 使用說明:

try{
		//可能出現異常的代碼
    
}catch(異常類型1 變量名1){
  		//處理異常的方式1
}catch(異常類型2 變量名2){
 		//處理異常的方式2
}catch(異常類型3 變量名3){
  		//處理異常的方式3
}
 ....
finally{
  		//必定會執行的代碼
}

說明:this

  1. finally是可選的。編碼

  2. 使用try將可能出現異常代碼包裝起來,在執行過程當中,一旦出現異常,就會生成一個對應異常類的對象,根據此對象的類型,去catch中進行匹配

  3. 一旦try中的異常對象匹配到某一個catch時,就進入catch中進行異常的處理。一旦處理完成,就跳出當前的try-catch結構(在沒寫finally的狀況。繼續執行其後的代碼)

  4. catch中的異常類型若是沒子父類關係,則誰聲明在上,誰聲明在下無所謂。

    catch中的異常類型若是知足子父類關係,則要求子類必定聲明在父類的上面。不然,報錯

  5. 經常使用的異常對象處理的方式: ① String getMessage() ② printStackTrace()

  6. 在try結構中聲明的變量,再出了try結構之後,就不能再被調用

  7. try-catch-finally結構能夠嵌套

如何看待代碼中的編譯時異常和運行時異常?

  1. 使用try-catch-finally處理編譯時異常,是得程序在編譯時就再也不報錯,可是運行時仍可能報錯。至關於咱們使用try-catch-finally將一個編譯時可能出現的異常,延遲到運行時出現。
  2. 開發中,因爲運行時異常比較常見,因此咱們一般就不針對運行時異常編寫try-catch-finally了。==針對於編譯時異常,咱們說必定要考慮異常的處理==。

2.2. finally的再說明:

  1. finally是可選的
  2. finally中聲明的是必定會被執行的代碼。即便catch中又出現異常了,try中return語句,catch中return語句等狀況。
  3. 像數據庫鏈接、輸入輸出流、網絡編程Socket等資源,JVM是不能自動的回收的,咱們須要本身手動的進行資源的釋放。此時的資源釋放,就須要聲明在finally中。

3. 異常處理方式二:

"throws + 異常類型"==寫在方法的聲明處==。指明此方法執行時,可能會拋出的異常類型。 一旦當方法體執行時,出現異常,仍會在異常代碼處生成一個異常類的對象,此對象知足throws後異常類型時,就會被拋出。異常代碼後續的代碼,就再也不執行!

4. 對比兩種處理方式

try-catch-finally:真正的將異常給處理掉了。 throws的方式只是將異常拋給了方法的調用者。==並沒真正將異常處理掉==。

5. 開發中應該如何選擇兩種處理方式?

  • 若是父類中被重寫的方法沒throws方式處理異常,則子類重寫的方法也不能使用throws,意味着若是子類重寫的方法中異常,必須使用try-catch-finally方式處理。
  • 執行的方法a中,前後又調用了另外的幾個方法,這幾個方法是遞進關係執行的。咱們建議這幾個方法使用throws的方式進行處理。而執行的方法a能夠考慮使用try-catch-finally方式進行處理。

補充: 方法重寫的規則之一: 子類重寫的方法拋出的異常類型不大於父類被重寫的方法拋出的異常類型

手動拋出異常對象

1.使用說明

在程序執行中,除了自動拋出異常對象的狀況以外,咱們還能夠手動的throw一個異常類的對象。

2.經典面試題

throw 和 throws區別: throw 表示拋出一個異常類的對象,生成異常對象的過程。聲明在方法體內。 throws 屬於異常處理的一種方式,聲明在方法的聲明處。

3.代碼示例

class Student{
	
	private int id;
	
	public void regist(int id) throws Exception {
		if(id > 0){
			this.id = id;
		}else{
			//手動拋出異常對象
//			throw new RuntimeException("您輸入的數據非法!");
//			throw new Exception("您輸入的數據非法!");
			throw new MyException("不能輸入負數");

		}		
	}

	@Override
	public String toString() {
		return "Student [id=" + id + "]";
	}
		
}

自定義異常類

1.如何自定義異常類

  1. 繼承於現的異常結構:RuntimeException 、Exception
  2. 提供全局常量:serialVersionUID(對類的惟一標識)
  3. 提供重載的構造器

2.代碼示例

public class MyException extends Exception{
	
	static final long serialVersionUID = -7034897193246939L;
	
	public MyException(){
		
	}
	
	public MyException(String msg){
		super(msg);
	}
}
相關文章
相關標籤/搜索