IO_異常處理

1:異常(理解)

(1)程序出現的不正常的情況。

(2)異常的體系

Throwable

|--Error嚴重問題,我們不處理。例如內存溢出

|--Exception

|--RuntimeException運行期異常,我們需要修正代碼

|--非RuntimeException 編譯期異常,必須處理的,否則程序編譯不通過

(3)異常的處理:

A:JVM的默認處理

把異常的名稱,原因,位置等信息輸出在控制檯,但是呢程序不能繼續執行了。

B:自己處理

a:try...catch...finally

自己編寫處理代碼,後面的程序可以繼續執行


 * try...catch...finally的處理格式:

 * try {

 * 可能出現問題的代碼;

 * }catch(異常名 變量) {

 * 針對問題的處理;

 * }finally {

 * 釋放資源;

 * }

 * 

 * 變形格式:

 * try {

 * 可能出現問題的代碼;

 * }catch(異常名 變量) {

 * 針對問題的處理;

 * }

 * 

 * 注意:

 * A:try裏面的代碼越少越好

 * B:catch裏面必須有內容,哪怕是給出一個簡單的提示

public class ExceptionDemo {
	public static void main(String[] args) {
		// 第一階段
		int a = 10;
		// int b = 2;
		int b = 0;

		try {
			System.out.println(a / b);
		} catch (ArithmeticException ae) {
			System.out.println("除數不能爲0");
		}

		// 第二階段
		System.out.println("over");
	}
}



 * A:一個異常

 * B:二個異常的處理

 * a:每一個寫一個try...catch

 * b:寫一個try,多個catch

 * try{

 * ...

 * }catch(異常類名 變量名) {

 * ...

 * }

 * catch(異常類名 變量名) {

 * ...

 * }

 * ...

 * 

 * 注意事項:

 * 1:能明確的儘量明確,不要用大的來處理。

 * 2:平級關係的異常誰前誰後無所謂,如果出現了子父關係,父必須在後面。

 * 

 * 注意:

 * 一旦try裏面出了問題,就會在這裏把問題給拋出去,然後和catch裏面的問題進行匹配,

 * 一旦有匹配的,就執行catch裏面的處理,然後結束了try...catch

 * 繼續執行後面的語句。

public class ExceptionDemo2 {
	public static void main(String[] args) {
		// method1();

		// method2();

		// method3();

		method4();
	}

	public static void method4() {
		int a = 10;
		int b = 0;
		int[] arr = { 1, 2, 3 };

		// 爺爺在最後
		try {
			System.out.println(a / b);
			System.out.println(arr[3]);
			System.out.println("這裏出現了一個異常,你不太清楚是誰,該怎麼辦呢?");
		} catch (ArithmeticException e) {
			System.out.println("除數不能爲0");
		} catch (ArrayIndexOutOfBoundsException e) {
			System.out.println("你訪問了不該的訪問的索引");
		} catch (Exception e) {
			System.out.println("出問題了");
		}

		// 爺爺在前面是不可以的
		// try {
		// System.out.println(a / b);
		// System.out.println(arr[3]);
		// System.out.println("這裏出現了一個異常,你不太清楚是誰,該怎麼辦呢?");
		// } catch (Exception e) {
		// System.out.println("出問題了");
		// } catch (ArithmeticException e) {
		// System.out.println("除數不能爲0");
		// } catch (ArrayIndexOutOfBoundsException e) {
		// System.out.println("你訪問了不該的訪問的索引");
		// }

		System.out.println("over");
	}

	// 兩個異常的處理
	public static void method3() {
		int a = 10;
		int b = 0;
		int[] arr = { 1, 2, 3 };

		try {
			System.out.println(arr[3]);
			System.out.println(a / b);
			// System.out.println(arr[3]);
		} catch (ArithmeticException e) {
			System.out.println("除數不能爲0");
		} catch (ArrayIndexOutOfBoundsException e) {
			System.out.println("你訪問了不該的訪問的索引");
		}

		System.out.println("over");
	}

	// 兩個異常
	public static void method2() {
		int a = 10;
		int b = 0;
		try {
			System.out.println(a / b);
		} catch (ArithmeticException e) {
			System.out.println("除數不能爲0");
		}

		int[] arr = { 1, 2, 3 };
		try {
			System.out.println(arr[3]);
		} catch (ArrayIndexOutOfBoundsException e) {
			System.out.println("你訪問了不該的訪問的索引");
		}

		System.out.println("over");
	}

	// 一個異常
	public static void method1() {
		// 第一階段
		int a = 10;
		// int b = 2;
		int b = 0;

		try {
			System.out.println(a / b);
		} catch (ArithmeticException ae) {
			System.out.println("除數不能爲0");
		}

		// 第二階段
		System.out.println("over");
	}
}


處理多個異常問題:

/*
 * JDK7出現了一個新的異常處理方案:
 * 		try{
 * 
 * 		}catch(異常名1 | 異常名2 | ...  變量 ) {
 * 			...
 * 		}
 * 
 * 		注意:這個方法雖然簡潔,但是也不夠好。
 * 			A:處理方式是一致的。(實際開發中,好多時候可能就是針對同類型的問題,給出同一個處理)
 *			B:多個異常間必須是平級關係。
 */
public class ExceptionDemo3 {
	public static void main(String[] args) {
		method();
	}

	public static void method() {
		int a = 10;
		int b = 0;
		int[] arr = { 1, 2, 3 };

		// try {
		// System.out.println(a / b);
		// System.out.println(arr[3]);
		// System.out.println("這裏出現了一個異常,你不太清楚是誰,該怎麼辦呢?");
		// } catch (ArithmeticException e) {
		// System.out.println("除數不能爲0");
		// } catch (ArrayIndexOutOfBoundsException e) {
		// System.out.println("你訪問了不該的訪問的索引");
		// } catch (Exception e) {
		// System.out.println("出問題了");
		// }

		// JDK7的處理方案
		try {
			System.out.println(a / b);
			System.out.println(arr[3]);
		} catch (ArithmeticException | ArrayIndexOutOfBoundsException e) {
			System.out.println("出問題了");
		}

		System.out.println("over");
	}

}


Demo:

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

/*
 * 在try裏面發現問題後,jvm會幫我們生成一個異常對象,然後把這個對象拋出,和catch裏面的類進行匹配。
 * 如果該對象是某個類型的,就會執行該catch裏面的處理信息。
 * 
 * 異常中要了解的幾個方法:
 * public String getMessage():異常的消息字符串		
 * public String toString():返回異常的簡單信息描述
 * 		此對象的類的 name(全路徑名)
 * 		": "(冒號和一個空格) 
 * 		調用此對象 getLocalizedMessage()方法的結果 (默認返回的是getMessage()的內容)
 * printStackTrace() 獲取異常類名和異常信息,以及異常出現在程序中的位置。返回值void。把信息輸出在控制檯。
 */
public class ExceptionDemo {
	public static void main(String[] args) {
		String s = "2014-11-20";
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		try {
			Date d = sdf.parse(s); // 創建了一個ParseException對象,然後拋出去,和catch裏面進行匹配
			System.out.println(d);
		} catch (ParseException e) { // ParseException e = new ParseException();
			// ParseException
			// e.printStackTrace();

			// getMessage()
			// System.out.println(e.getMessage());
			// Unparseable date: "2014-11-20"

			// toString()
			// System.out.println(e.toString());
			// java.text.ParseException: Unparseable date: "2014-11-20"
			
			e.printStackTrace();
			//跳轉到某個指定的頁面(index.html)
		}
		
		System.out.println("over");
	}
}



b:throws

把自己處理不了的,在方法上聲明,告訴調用者,這裏有問題


Demo:

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

/*
 * 有些時候,我們是可以對異常進行處理的,但是又有些時候,我們根本就沒有權限去處理某個異常。
 * 或者說,我處理不了,我就不處理了。
 * 爲了解決出錯問題,Java針對這種情況,就提供了另一種處理方案:拋出。
 * 
 * 格式:
 * 		throws 異常類名
 * 		注意:這個格式必須跟在方法的括號後面。
 * 
 * 注意:
 * 		儘量不要在main方法上拋出異常。
 * 		但是我講課爲了方便我就這樣做了。
 * 
 * 小結:
 * 		編譯期異常拋出,將來調用者必須處理。
 * 		運行期異常拋出,將來調用可以不用處理。
 */
public class ExceptionDemo {
	public static void main(String[] args) {
		System.out.println("今天天氣很好");
		try {
			method();
		} catch (ParseException e) {
			e.printStackTrace();
		}
		System.out.println("但是就是不該有霧霾");

		method2();
	}

	// 運行期異常的拋出
	public static void method2() throws ArithmeticException {
		int a = 10;
		int b = 0;
		System.out.println(a / b);
	}

	// 編譯期異常的拋出
	// 在方法聲明上拋出,是爲了告訴調用者,你注意了,我有問題。
	public static void method() throws ParseException {
		String s = "2014-11-20";
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		Date d = sdf.parse(s);
		System.out.println(d);
	}
}




(4)面試題

A:編譯期異常和運行期異常的區別?

編譯期異常 必須要處理的,否則編譯不通過

運行期異常 可以不處理,也可以處理

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

/*
 * 編譯時異常和運行時異常的區別
 * 編譯期異常:Java程序必須顯示處理,否則程序就會發生錯誤,無法通過編譯
 * 運行期異常:無需顯示處理,也可以和編譯時異常一樣處理
 */
public class ExceptionDemo {
	public static void main(String[] args) {
		// int a = 10;
		// int b = 0;
		// if (b != 0) {
		// System.out.println(a / b);
		// }

		String s = "2014-11-20";
		// SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		// Date d = sdf.parse(s);
		try {
			Date d = sdf.parse(s);
			System.out.println(d);
		} catch (ParseException e) {
			// e.printStackTrace();
			System.out.println("解析日期出問題了");
		}
	}
}



B:throw和throws是的區別

throw:

在方法體中,後面跟的是異常對象名,並且只能是一個

throw拋出的是一個異常對象,說明這裏肯定有一個異常產生了

throws:

在方法聲明上,後面跟的是異常的類名,可以是多個

throws是聲明方法有異常,是一種可能性,這個異常並不一定會產生

Demo:

/*
 * throw:如果出現了異常情況,我們可以把該異常拋出,這個時候的拋出的應該是異常的對象。
 * 
 * throws和throw的區別(面試題)
	throws
		用在方法聲明後面,跟的是異常類名
		可以跟多個異常類名,用逗號隔開
		表示拋出異常,由該方法的調用者來處理
		throws表示出現異常的一種可能性,並不一定會發生這些異常
	throw
		用在方法體內,跟的是異常對象名
		只能拋出一個異常對象名
		表示拋出異常,由方法體內的語句處理
		throw則是拋出了異常,執行throw則一定拋出了某種異常
 */
public class ExceptionDemo {
	public static void main(String[] args) {
		// method();
		
		try {
			method2();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static void method() {
		int a = 10;
		int b = 0;
		if (b == 0) {
			throw new ArithmeticException();
		} else {
			System.out.println(a / b);
		}
	}

	public static void method2() throws Exception {
		int a = 10;
		int b = 0;
		if (b == 0) {
			throw new Exception();
		} else {
			System.out.println(a / b);
		}
	}
}



(5)finally關鍵字及其面試題

A:finally用於釋放資源,它的代碼永遠會執行。特殊情況:在執行到finally之前jvm退出了

Demo:

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

/*
 * finally:被finally控制的語句體一定會執行
 * 注意:如果在執行到finally之前jvm退出了,就不能執行了。
 * 
 * A:格式
 * 		try...catch...finally...
 * B:用於釋放資源,在IO流操作和數據庫操作中會見到
 */
public class FinallyDemo {
	public static void main(String[] args) {
		String s = "2014-11-20";
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

		Date d = null;
		try {
			// System.out.println(10 / 0);
			d = sdf.parse(s);
		} catch (ParseException e) {
			e.printStackTrace();
			System.exit(0);
		} finally {
			System.out.println("這裏的代碼是可以執行的");
		}

		System.out.println(d);
	}
}



B:面試題

a:final,finally,finalize的區別?

b:如果在catch裏面有return,請問finally還執行嗎?如果執行,在return前還是後

會,前。

C:異常處理的變形

try...catch...finally

try...catch...

try...catch...catch...

try...catch...catch...fianlly

try...finally


Demo:

/*
 * 面試題:
 * 1:final,finally和finalize的區別
 * final:最終的意思,可以修飾類,成員變量,成員方法
 * 		修飾類,類不能被繼承
 * 		修飾變量,變量是常量
 * 		修飾方法,方法不能被重寫
 * finally:是異常處理的一部分,用於釋放資源。
 * 		一般來說,代碼肯定會執行,特殊情況:在執行到finally之前jvm退出了
 * finalize:是Object類的一個方法,用於垃圾回收
 * 
 * 2:如果catch裏面有return語句,請問finally裏面的代碼還會執行嗎?
 *   如果會,請問是在return前,還是return後。
 * 	   會。前。
 * 
 * 	 準確的說,應該是在中間。
 * 
 * 3:try...catch...finally的格式變形
 * 		A:try...catch...finally
 * 		B:try...catch
 * 		C:try...catch...catch...
 * 		D:try...catch...catch...finally
 * 		E:try...finally
 * 			這種做法的目前是爲了釋放資源。
 */
public class FinallyDemo2 {
	public static void main(String[] args) {
		System.out.println(getInt());
	}

	public static int getInt() {
		int a = 10;
		try {
			System.out.println(a / 0);
			a = 20;
		} catch (ArithmeticException e) {
			a = 30;
			return a;
			/*
			 * return a在程序執行到這一步的時候,這裏不是return a而是return 30;這個返回路徑就形成了。
			 * 但是呢,它發現後面還有finally,所以繼續執行finally的內容,a=40
			 * 再次回到以前的返回路徑,繼續走return 30;
			 */
		} finally {
			a = 40;
			return a;//如果這樣結果就是40了。
		}
		// return a;
	}
}


(6)自定義異常

繼承自Exception或者RuntimeException,只需要提供無參構造和一個帶參構造即可


 * java不可能對所有的情況都考慮到,所以,在實際的開發中,我們可能需要自己定義異常。

 * 而我們自己隨意的寫一個類,是不能作爲異常類來看的,要想你的類是一個異常類,就必須繼承自Exception或者RuntimeException

 * 

 * 兩種方式:

 * A:繼承Exception

 * B:繼承RuntimeException


MyException類:

package cn.itcast_08;

/*
 * java不可能對所有的情況都考慮到,所以,在實際的開發中,我們可能需要自己定義異常。
 * 而我們自己隨意的寫一個類,是不能作爲異常類來看的,要想你的類是一個異常類,就必須繼承自Exception或者RuntimeException
 * 
 * 兩種方式:
 * A:繼承Exception
 * B:繼承RuntimeException
 */
public class MyException extends Exception {
	public MyException() {
	}

	public MyException(String message) {
		super(message);
	}
}


Teacher類:

package cn.itcast_08;

public class Teacher {
	public void check(int score) throws MyException {
		if (score > 100 || score < 0) {
			throw new MyException("分數必須在0-100之間");
		} else {
			System.out.println("分數沒有問題");
		}
	}

	// 針對MyException繼承自RuntimeException
	// public void check(int score) {
	// if (score > 100 || score < 0) {
	// throw new MyException();
	// } else {
	// System.out.println("分數沒有問題");
	// }
	// }
}


Student類:

package cn.itcast_08;

import java.util.Scanner;

/*
 * 自定義異常測試類
 */
public class StudentDemo {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		System.out.println("請輸入學生成績:");
		int score = sc.nextInt();

		Teacher t = new Teacher();
		try {
			t.check(score);
		} catch (MyException e) {
			e.printStackTrace();
		}
	}
}


(7)異常的注意實現

A:父的方法有異常拋出,子的重寫方法在拋出異常的時候必須要小於等於父的異常 

B:父的方法沒有異常拋出,子的重寫方法不能有異常拋出

C:父的方法拋出多個異常,子的重寫方法必須比父少或者小

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

/*
 * 異常注意事項:
 * A:子類重寫父類方法時,子類的方法必須拋出相同的異常或父類異常的子類。(父親壞了,兒子不能比父親更壞)
 * B:如果父類拋出了多個異常,子類重寫父類時,只能拋出相同的異常或者是他的子集,子類不能拋出父類沒有的異常
 * C:如果被重寫的方法沒有異常拋出,那麼子類的方法絕對不可以拋出異常,如果子類方法內有異常發生,那麼子類只能try,不能throws
 */
public class ExceptionDemo {

}

class Fu {
	public void show() throws Exception {
	}

	public void method() {
	}
}

class Zi extends Fu {
	@Override
	public void show() throws ArithmeticException {

	}

	@Override
	public void method() {
		// String s = "2014-11-20";
		// SimpleDateFormat sdf = new SimpleDateFormat();
		// Date d = sdf.parse(s);
		// System.out.println(d);
	}
}

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