【黑馬程序員】面向對象(五) 第九天

-------  android培訓java培訓java學習型技術博客、期待與您交流! ----------

知識點

異常處理能夠使一個方法給它的調用者拋出一個異常。
異常發生在一個方法的執行過程中。RuntimeException和Error都是免檢異常,其它所有異常都是必檢的。
當聲明一個方法時,如果這個方法可能拋出一個必檢異常,則必須聲明爲必檢異常,告訴編譯器可能會出現什麼錯誤。
聲明異常的關鍵字是throws,而拋出異常的關鍵字是throw
如果調用了必檢異常的方法,必須將該方法調用放在try語句中。在方法不斷重複直到異常被捕獲或者傳遞給Main方法。
可以從一個通用的父類派生出各種不同的異常類。如果一個catch塊捕獲到父類的異常對象,它也能捕獲這個父類的子類的所有異常對象。
在catch塊中,異常被指定順序是非常重要的。如果在一個類的父類的異常對象之前沒有指定這個類的一個異常對象,就會導致一個編譯錯誤。
當方法發生異常時,如果異常沒有被捕獲,方法將會立即退出。如果方法想在退出前執行一些任務,可以在方法中捕獲這個異常,然後再重新拋給真正的處理器。
任何情況下都會執行finally塊中的代碼,不管try塊中是否出現或者捕獲了異常。
異常處理將錯誤處理代碼從正常的程序設計任務中分離出來,這樣,就會使程序更易於閱讀和修改。
不應該使用異常處理代替簡單的測試。 應該儘可能地測試簡單異常,將異常處理保留爲處理那些無法用if語句處理的異常。

01)內部類訪問規則(一)

1:內部類可以直接訪問外部類中的成員,包括私有。
之所以可以直接訪問外部類中的成員,是因爲內部類中持有了一個外部類的引用,格式:外部類名.this
2:外部類要訪問內部類,必須要建立內部類對象。
public class InnerClassDemo {
	public static void main(String[] args) {
		//直接訪問內部類中的成員。
		Outer.Inner in = new Outer().new Inner();
		in.function();
		System.out.println("------------");
		Outer o = new Outer();
		o.method();
	}
}
class Outer{
	private int x = 3;
	void method(){
		Inner in = new Inner();//創建內部類Inner對象。
		in.function();
	}
	
	class Inner{//內部類
		void function(){
			System.out.println("Innner: " + x);
		}
	}
}
運行結果如下圖所示:


02)靜態內部類

public class InnerClassDemo_2 {
	public static void main(String[] args) {
		new Outer_1.Inner().function_1();//直接訪問static內部類中的非靜態成員。
		System.out.println("-------------");
		Outer_1.Inner_2.function_2();//直接訪問static內部類中的靜態成員。
	}
}
class Outer_1{
	private static int x = 3;
	static class Inner{//靜態內部類
		void function_1() {
			System.out.println("Inner: " + x);
		}
	}
	static class Inner_2{//靜態內部類
		static void function_2() {
			System.out.println("Inner: " + x);
		}
	}
}
運行結果如下圖所示:


03)內部類定義原則

當描述事物時,事物內部還有事物,該事物用內部類來描述。
因爲該事物需要使用外部事物的內容。

04)匿名內部類




05)異常概述

/*
 * 異常:就是程序在運行時出現不正常情況。
 * 異常由來:問題也是現實生活中一個具體的事物,也可以通過java的類的形式進行描述。並封裝成對象。
 * 			其實就是java對不正常情況進行描述後的對象體現。
 * 對於問題的劃分:兩種:一種是嚴重的問題,一種是非嚴重的問題。
 * 對於嚴重的,java通過Error類進行描述。對於非嚴重的,java通過Exception類進行描述。
 */
public class ExceptionDemo {
	public static void main(String[] args) {
		Demo d = new Demo();
		int a = d.div(10, 3);
		System.out.println("A: " + a);
//		int b = d.div(10, 0);//除數不能爲0。
//		System.out.println("B: " + b);//異常:ArithmeticException
	}
}
class Demo{
	int div(int a, int b){
		return a / b;
	}
}

06)try-catch

一:異常的處理:Java提供了特有的語句進行處理。
try{
需要被檢測的代碼。
}catch(異常類 變量){
處理異常的代碼。(處理方式)
}finally{
一定會執行的語句。
}
二:對捕獲的異常對象進行常見方法操作。
String getMessage() :獲取異常信息
String toString():獲取異常名稱和異常信息。
String printStackTrace():獲取異常名稱、異常信息和異常出現的位置。
public class ExceptionDemo_2 {
	public static void main(String[] args) {
		Demo_2 d = new Demo_2();
		try{
			int a = d.div(10, 3);
			System.out.println("A: " + a);
			int b = d.div(a, 0);//異常:ArithmeticException
			System.out.println("B: " + b);
		}catch(Exception e){//Exception e = new ArithmeticException();//多態。
			System.out.println("除數不能爲O");
			System.out.println(e.getMessage());//打印異常信息
			System.out.println(e.toString());//打印異常名稱+異常信息。
			e.printStackTrace();//打印異常名稱+異常信息+異常出現的位置。
								//這是JVM默認的異常處理機制。
		}
	}
}
class Demo_2{
	int div(int a, int b){
		return a / b;
	}
}
運行結果如下圖所示:


07)異常聲明(throws)

public class ExceptionDemo_3 {
	public static void main(String[] args){
		Demo_3 d = new Demo_3();
		try{
			int a = d.div(100, 10);
			System.out.println("A: " + a);
			int b = d.div(a, 0);//出現異常後,下面一行語句將不執行。
			System.out.println("B: " + b);
		}catch (Exception e){
			System.out.println(e.toString());
		}
		
	}
}
class Demo_3{
	int div(int a, int b) throws Exception{//在功能上通過throws的關鍵字聲明瞭該功能有可能會出現問題。
		return a / b;
	}
}
運行結果如下圖所示:


08)多異常處理

1:聲明異常時,建議聲明更爲具體的異常。這樣處理的可以更具體。
2:對方聲明幾個異常,就應該有幾個catch塊。不要定義多餘的catch塊。
如果多個catch塊中的異常出現繼承關係,父類異常catch塊放在最後。
建議:在進行catch處理時,catch中一定要定義具體的處理方式。不要簡單定義一句:e.printStackTrace(),也不要就簡單的就書寫一條輸出語句。
public class ExceptionDemo_4 {
	public static void main(String[] args) {
		Demo_4 d = new Demo_4();
		try{
			int a = d.div(5, 2);
			System.out.println("A: " + a);
		}catch (ArithmeticException e){
			System.out.println("除數不能爲0: " + e.toString());
		}catch (ArrayIndexOutOfBoundsException e){//被捕獲
			System.out.println("下標越界異常: " + e.toString());
		}catch (Exception e){
			System.out.println("發現異常: " + e.toString());
		}
	}
}
class Demo_4{
	int div(int a, int b) throws ArithmeticException, ArrayIndexOutOfBoundsException{
		int[] arr = new int[a];
		System.out.println(arr[5]);//發生異常,結束語句。
		return a / b;
	}
}
運行結果如下圖所示:


09)**自定義異常

因爲項目中會出現特有的問題,而這些問題並未被java所描述並封裝對象。所以對於這些特有的問題可以按照java的對問題封裝的思想。將這些特有的問題進行自定義的異常封裝。
/*
 * 自定義異常:
 * 需求:在本程序中,對於除數是負數,也視爲錯誤的是無法進行運算的。那麼就需要對這個問題進行自定義的描述。
 * 當函數內部出現了throw拋出異常對象,那麼就必須要給對應的處理動作。
 * 要麼在catch內部try catch處理。
 * 要麼在函數上聲明讓調用者處理。
 * 
 * 一般情況下,函數內部出現異常,函數上需要聲明。
 * 定義異常信息:因爲父類中已經把異常信息的操作都完成了。
 * 				所以子類在構造時,只要將異常信息傳遞給父類,通過super語句。就可以直接通過getMessage()方法獲取自定義的異常信息。
 * 
 */
public class ExceptionDemo_5 {
	public static void main(String[] args) {
		Demo_5 d = new Demo_5();
		try{
			int a = d.div(10, -6);
			System.out.println("A: " + a);
		}catch (FuShuException e){
			System.out.println(e.toString());
			System.out.println("錯誤的負數是: " + e.getValue());
		}
		
	}
}
class Demo_5{
	int div(int a, int b) throws FuShuException {//拋出異常
		if (b < 0)
			throw new FuShuException("出現了除數爲負數的情況", b);
		return a / b;
	}
}
class FuShuException extends Exception{
	private int value;
	FuShuException(){
		super();
	}
	FuShuException(String mag, int value){
		super(mag);
		this.value = value;
	}
	public int getValue(){
		return value;
	}
}
運行結果如下圖所示:


10)throw和throws的區別
throws使用在函數上,throw使用在函數內。
throws後面跟的是異常類。可以跟多個,用逗號“,”隔開。
throw後面跟的是異常對象。

11)RuntimeException
RuntimeException的異常如果在函數內被拋出,在函數上可以不聲明。
如果在函數上聲明瞭該異常,調用者可以不用進行處理。
/*
 * 練習:湯姆在看電視。
 * 思考湯姆在看電視時會遇到的問題。
 * 
 * 比如問題是:電視卡屏、電視冒煙、傑瑞來搗亂。
 * 對問題進行描述,封裝成對象。
 * 當出現第一種情況:電視機卡屏。重啓電視機。
 * 當出現第二種情況:電視機冒煙。湯姆找斯派克修理電腦。
 * 當出現第三種情況:傑瑞來搗亂。湯姆抓傑瑞。
 */
public class ExceptionDemoTest {
	public static void main(String[] args) {
		Tom tom = new Tom("湯姆");
		try{
			tom.userTV();
		}catch (SPKException e){
			System.out.println(e.getMessage());
		}
	}
}
class TV{//電視機
	private int state = 2;//其它的都代表正常狀態。這裏初始化state爲第二種狀況:電視機冒煙。
	public void run() throws KaPException, MaoYException, JieRException{
		if (state == 1)
			throw new KaPException("第一種情況:電視機卡屏");
		if (state == 2)
			throw new MaoYException("第二種情況:電視機冒煙");
		if (state == 3)
			throw new JieRException("第三種情況:傑瑞來搗亂");
		else
			System.out.println("電視機正常運行");
	}
	public void reset(){//電視機出現問題後重啓.
		System.out.println("重啓電視機");//爲了方便把關機再開機併爲重啓。
	}
}

class Tom{//湯姆使用電視機
	private String name;
	private TV tv;
	Tom(String name){
		this.name = name;
		tv = new TV();
	}
	public void userTV() throws SPKException{//拋給調用者
		try{
			tv.run();
			System.out.println("看電視");
		}catch (KaPException e){
			System.out.println(e.getMessage());
			tv.reset();
		}catch (MaoYException e){
			System.out.println(e.getMessage());
			System.out.println("不看電視啦");
			throw new SPKException("湯姆找斯派克修理電視機");//湯姆處理不了異常,只能拋出異常。
		}catch (JieRException e){
			System.out.println(e.getMessage());
			System.out.println("湯姆抓傑瑞");
		}
	}
}

class KaPException extends Exception{//卡屏異常
	KaPException(String mag){
		super(mag);
	}
}
class MaoYException extends Exception{//冒煙異常
	MaoYException(String mag){
		super(mag);
	}
}
class JieRException extends Exception{//傑瑞搗亂異常
	JieRException(String mag){
		super(mag);
	}
}
class SPKException extends MaoYException{//異常拋給斯派克
	SPKException(String mag){
		super(mag);
	}
}
private int state = 2;//其它的都代表正常狀態。這裏初始化state爲第二種狀況:電視機冒煙。
運行結果如下圖所示:


附言:我是Java新人,如有錯誤的地方請指出。
                         每天學習一點點,糾錯一點點,進步很大點。

-------  android培訓java培訓java學習型技術博客、期待與您交流! ----------


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