異常詳解

一.異常

1.定義:Java程序也是會存在某些不正常的情況的,這些不正常的情況我們就統稱異常。

2.異常體系:

--------| Throwable(Throwable類是Java語言中所有錯誤或異常的超類)

------------| Error(錯誤,錯誤一般是由Jvm或者是硬件引發的問題,所以我們一般不會通過修改代碼去處理錯誤的)

------------| Exception(異常,是需要通過代碼去處理的


3.Throwable常用的方法:

(1) toString():返回當前異常對象的完整類名+病態信息。
(2) getMessage():返回的是創建Throwable傳入的字符串信息。
(3) printStackTrace():打印異常的棧信息。這個方法以後會經常用到,有了這個方法以後我們想找這個程序所存在的問題是非常方便的,很快就可以定位到。而且打印出來的異常信息,也會讓我們知道這是個什麼樣子的病。

4.實例:

(1) 實例

class Demo1{
	public static void main(String[] args){
		//創建了一個Throwable對象。
		Throwable t = new Throwable("頭暈,感冒……");
		String info = t.toString();
		String message = t.getMessage();
		System.out.println("toString:"+info);
		//java.lang.Throwable  包名+類名 = 完整類名
		System.out.println("message:"+message);
	}
}

運行結果如下圖所示:


(2) 實例二

class Demo2{
	public static void main(String[] args){
		test();
	}
	public static void test(){
		Throwable t = new Throwable();//相當於程序在這裏生病
		t.printStackTrace();
	}
}

運行結果如下圖所示:


運行結果顯示,最上面一行是描述這種病的類,先告訴你程序有了哪些病,緊接着這個病是由第6行引發的,而第6行的病導致了第3行的調用也出了問題。這就很像醫生看病,先告訴你是什麼病,這個病現在是在哪一行,一層一層的追蹤病源下去。

5.如何區分錯誤與異常呢?

如果程序出現了不正常的信息,如果不正常的信息的類名是以Error結尾的,那麼肯定是一個錯誤;如果是以Exception結尾的,那麼肯定就是一個異常。

二.異常的處理

1.實例一:

(1) 實例:

class Demo1{
	public static void main(String[] args){
		div(4,0);
	}
	public static void div(int a,int b){
		int c = a/b;
		System.out.println("c="+c);
	}
}

(2) 運行結果如下圖所示:


(3) 上面的信息是通過printStackTrace方法打印出來,(必須得有異常的對象才能調用到這個方法)那麼異常對象從何而來呢?

 Jvm運行到a/b這個語句的時候,發現b爲0,除數爲0在我們現實生活中是屬於不正常的情況,Jvm一旦發現了這種不正常的情況時候,那麼Jvm就會馬上創建一個對應的異常對象,並且會調用這個異常對象 的printStackTrace的方法來處理。當Jvm遇到一個異常時比如在c = a/b發現除數爲0.就不會再正常的繼續往下執行。要想程序可以繼續往下執行就必須要處理這個異常。如果不處理異常,程序還是會在這裏生病,就不會再繼續往下執行。這時候我們就要學習異常的處理方式;

2.處理異常的兩種方式:

(1) 方式一:捕獲處理;

(2) 方式二:拋出處理;

和我們現實中有病要去醫院,醫院的處理方式也是兩種:如果年輕人得什麼病,醫院會要求你住院,這就相當於捕獲處理;如果是那種老人,去小鎮上的醫院治病,那兒的醫生不敢接,碰到這種情況,醫院會拋出處理,轉到大醫院去。

3.捕獲處理:

(1) 捕獲處理的格式:

try{
	可能發生異常的代碼;
}catch(捕獲的異常類型 變量名){
	處理異常的代碼;
}

注意:必須強調是可能發生異常的代碼,而不是發生異常的代碼,因爲c = a/b並不是一定會出現異常,如果b不爲0就不會有異常,所以只是有可能出現異常而已。

(2) 捕獲處理要注意的細節:

① 如果try塊中代碼出了異常經過了處理之後,那麼try-catch塊外面的代碼可以正常執行。
② 如果try塊中出了異常的代碼,那麼在try塊中出現異常代碼後面的代碼是不會執行了。
③ 一個try塊後面是可以跟有多個catch塊的,也就是一個try塊可以捕獲多種異常的類型。

④ 一個try塊可以捕獲多種異常的類型,但是捕獲的異常類型必須從小到大進行捕獲,否則編譯報錯。

(3) 捕獲處理實例

①實例一: 一個try塊中只有一種類型的異

class Demo2{
	public static void main(String[] args){
		div(4,0);
	}
	public static void div(int a,int b){
		int c = 0;
		try{
			//變量c的作用域是這個大括號,出了這個大括號就不可見,所以應該把c聲明到外面
			c = a/b;
		}catch(ArithmeticException e){//通過變量e就可以找到這個異常對象
			//處理異常的代碼
			System.out.println("toString:"+e.toString());
		}
		System.out.println("c="+c);//經過異常處理後下面的代碼也可以輸出
	}
}

運行結果如下圖所示:


②實例二: 一個try塊中有多種類型的異常

class Demo3{
	public static void main(String[] args){
		int[] arr = null;
		div(4,2,arr);
	}
	public static void div(int a,int b,int[] arr){
		int c = 0;
		try{
			c = a/b;
			System.out.println("數組的長度:"+arr.length);
		}catch(ArithmeticException e){
			//處理異常的代碼
			System.out.println("toString:"+e.toString());
		}
		System.out.println("c="+c);
	}
}

運行結果如下圖所示:


疑問一:爲什麼有處理異常的代碼,但卻沒有輸出try-catch塊外的語句?

因爲代碼中捕獲處理捕獲的是除數爲0的異常,而現在報的是空指針異常,因爲捕獲的不是這種異常,所以不會進行處理。就好像你感冒發燒跑去婦產科那裏也不會接收你,這時候就必須再加一個捕獲異常處理。如下所示:

class Demo4{
	public static void main(String[] args){
		int[] arr = null;
		div(4,2,arr);
	}
	public static void div(int a,int b,int[] arr){
		int c = 0;
		try{
			c = a/b;
			System.out.println("數組的長度:"+arr.length);
		}catch(ArithmeticException e){
			//處理異常的代碼
			System.out.println("toString:"+e.toString());
		}catch(NullPointerException e){
			System.out.println("出現了空指針異常");
		}
		System.out.println("c="+c);
	}
}

運行結果如下圖所示:


③實例三:Exception類是所有異常類的父類。

class Demo5{
	public static void main(String[] args){
		int[] arr = null;
		div(4,2,arr);
	}
	public static void div(int a,int b,int[] arr){
		int c = 0;
		try{
			c = a/b;
			System.out.println("數組的長度:"+arr.length);
		}catch(Exception e){
			//此處運用了多態,Exception e = new NullPointerException();
			System.out.println("我是急診室,包治百病!");
		}
		System.out.println("c="+c);
	}
}

運行結果如下圖所示:


註解:如果出現算術異常,這個捕獲異常也會起作用,同樣用到的也是多態來捕獲,父類指向子類的對象。如果同時有Exception,和其他子類異常,應該把Exception放在最後一個捕獲,如果把Exception放在前面會報錯,因爲它已經攔截了所有類型的異常,當你出現任何類型的異常時它都能捕獲,所以導致後面的捕獲都沒有機會執行到,因爲Java編譯器不允許寫廢話。

④實例四:一個try塊可以捕獲多種異常的類型,但是捕獲的異常類型必須從小到大進行捕獲,否則編譯報錯。

class Demo6{
	public static void main(String[] args){
		int[] arr = null;
		div(4,0,arr);
	}
	public static void div(int a,int b,int[] arr){
		int c = 0;
		try{
			c = a/b;
			System.out.println("數組的長度:"+arr.length);
		}catch(ArithmeticException e){
			//處理異常的代碼
			System.out.println("toString:"+e.toString());
		}catch(NullPointerException e){
			System.out.println("出現了空指針異常");
		}catch(Exception e){
			System.out.println("我是急診室,包治百病!");
		}
		System.out.println("c="+c);
	}
}

運行結果如下圖所示:


疑問二:既然Exception能攔截所有類型的異常,那麼以後捕獲處理的時候是否直接捕獲Exception即可?

這種想法是錯誤的,因爲我們在現實開發中遇到不同的異常類型的時候,往往會有不同的處理方式,所以要分開不同的異常類型處理。比如說:當一個音樂播放器遇到卡頓時的處理方式是會將異常信息發送給服務器,服務器獲取到這個異常後處理髮布新的版本;如果遇到下載音樂時WIFI突然斷開,處理方式就不會再發送到服務器,而是保存他目前已經下載的信息和進度,等連上WIFI後繼續下載。

4.拋出處理:

(1) 拋出處理主要用到兩個關鍵字:throw和throws;

(2) 拋出處理要注意的細節:

① 如果一個方法的內部拋出了一個編譯時異常對象,那麼必須要在方法上聲明拋出。

原因:因爲一個方法的內部拋出一個異常對象,也就意味着這個方法在某種情況下是存在着危險性的,既然是危險的東西肯定要提示用戶,就好像一棟樓會有安全通道這種提示信息,因爲會有着火的風險,對於用戶來說,一個方法的內部如何實現用戶是不知道的,用戶只能看到方法的聲明部分,如果方法的聲明上寫上這句話,那麼我們就會意識到用這個方法可能會存在出異常的情況。我們就會知道用這個方法會有一定的危險性。所以爲了用戶調用這個方法的安全性考慮,如果我們在方法的內部拋出了一個異常對象,就必須要在方法上聲明拋出。因爲調用者只能看到方法的聲明部分,在方法上聲明拋出Exception的意義就是告訴調用者使用這個方法有可能存在着哪種危險。

② 如果調用了一個聲明拋出編譯時異常 的方法,那麼調用者必須要處理異常。

原因:如果在方法內部拋出了一個異常,誰調用了這個方法,那麼這個異常對象就會拋給誰,也就是說div(4,0)調用這個方法,那麼異常對象就會拋給調用它的main方法中,那麼main方法也會出問題。

③ 如果一個方法內部拋出了一個異常對象,那麼throw語句後面的代碼都不會再執行了(一個方法遇到了throw關鍵字,該方法也會馬上停止執行的)。

④ 在一種情況下,只能拋出一種類型異常對象。

(3) throw 與throws兩個關鍵字的區別:

① throw關鍵字是用於方法內部的,throws是用於方法聲明上的。

② throw關鍵字是用於方法內部拋出一個異常對象的,throws關鍵字是用於在方法聲明上聲明拋出異常類型的。

③ throw關鍵字後面只能有一個異常對象,throws後面一次可以聲明拋出多種類型的異常。

(4) 實例:

①實例一:如果調用了一個聲明拋出異常的方法,那麼調用者必須要處理異常

class Demo1{
	public static void main(String[] args){
		try{
			div(4,0);//調用了一個聲明拋出異常類型的方法
		}catch(Exception e){
			System.out.println("出現異常了");
			e.printStackTrace();
		}
	}
	public static void div(int a,int b) throws Exception{
		if(b == 0){
			throw new Exception();//拋出一個異常對象
		}
		int c = a/b;
		System.out.println("c="+c);
	}
}

運行結果如下圖所示:


疑問:爲什麼不能輸出c?

當b = 0時,通過throw new Exception( )拋出一個異常對象,c並不會輸出,道理也很簡單,就好比你去醫院看病,醫院都不收你,把你拋給上一級醫院,根本不對你的病情做任何處理,自然你的病情也不會好,這時候c就沒有輸出。

②實例二:

調用者也可以不處理異常,而是把異常再往上一級拋,如果它的調用者是在main方法中,Jvm調用main方法,那麼main方法會把異常拋給Jvm,而Jvm處理異常的方式是打印異常的棧信息。

class Demo2{
	public static void main(String[] args) throws Exception{
		div(4,0);//調用了一個聲明拋出異常類型的方法
	}
	public static void div(int a,int b) throws Exception{
		if(b == 0){
			throw new Exception();//拋出一個異常對象
		}
		int c = a/b;
		System.out.println("c="+c);
	}
}

運行結果如下圖所示:


(5) 疑問:何時使用拋出處理?何時使用捕獲處理?

①如果你需要通知到調用者,你的代碼出了問題,那麼這時候就使用拋出處理.

②如果代碼是直接與用戶打交道遇到了異常千萬不要再拋,再拋的話,就給了用戶了,這時候就應該使用捕獲處理。

(6) 使用拋出處理的原則


MVC模式會把代碼分成三層來管理,WEB層的代碼是用來展示數據給用戶去查看的,WEB層的代碼是與用戶打交道的;service層(業務邏輯層)負責把WEB層需要的數據處理成WEB層需要的格式;dao層(數據持久層)的代碼主要是用於保存、刪除、查詢數據的,主要負責與數據庫打交道。數據持久層會把查詢出的數據交給業務邏輯層,業務邏輯層會對傳過來的數據進行篩選、格式化篩選出符合WEB層需求的東西,經過service層的代碼過濾後會把代碼交給WEB層。所以,WEB層需要數據的話會和service層要,service層需要數據的話會和dao層要,也就是說WEB層會調用service層的代碼,service層的代碼會調用dao層的代碼。假設用戶需要在點餐系統中查詢出所有的菜名,當用戶點擊展示所有菜名時,就會調用到service層的代碼,service層就會調用daodao層的代碼,這時候dao層就要執行select * from foods;去查詢數據庫中的所有菜名,假設在查詢的過程中mysql數據庫的服務器關閉了,這時候就會出異常。這時候dao層的代碼出現了異常,如果dao層對異常的處理只是輸出,被處理過之後對於service層來說,service層並不知道dao層出了問題,因爲dao層已經把這個異常給處理掉了,所以service層會認爲這個數據查詢正確,service層就會對這個數據進行處理,因爲沒有查出來所以數據也是空的,這時候service層就會把空的數據給WEB層,WEB層拿到空的數據後,就會把空的展示給用戶什麼菜都沒有。所以dao層出現異常用捕獲處理是不行的,一般會有一個變量e指向出現異常的對象,我們捕獲到這個對象後往往會把這個異常對象通過throw e拋出去,這時候service層調用dao層的代碼後,這時候dao層會把異常拋給service層,service層接到異常後就會知道dao層做查詢時出了問題,這時候service層對這個異常的處理也不能是隻輸出一句話,而應該捕獲到這個異常後再把它拋出去,這時候WEB層就會接到這個異常,這時候WEB層就不能再拋出這個異常了,再拋就會拋給用戶,而用戶什麼都不懂,凡是與用戶打交道的代碼,拿到這個異常千萬不要拋,這時候WEB層就會對捕獲到的異常做處理一般是跳轉到一個友好的頁面。

三.自定義異常類

1.sun公司提供了很多的異常類給我們用於描述程序中各種不正常的情況,但是sun公司給我們提供的異常類還不足以描述我們現實生活中所有不正常情況,那麼這時候我們就需要自定義異常類。

2.自定義異常類的步驟:自定義一個類繼承Exception即可。

3.實例

(1) 實例一:

①需求:模擬feiQ上線的時候,如果沒有插上網線,那麼就拋出一個沒有插上網線的異常,如果已經插上了網線,那麼就正常顯示好友列表。

②分析:異常處理有兩種方式,分別是捕獲處理和拋出處理,首先我們實現插上網線顯示好友列表的需求。

③插上網線顯示好友列表:

class NoIpException extends Exception{
	public NoIpException(String message){
		super(message);  //調用了Exception一個參數的構造函數。
	}

}
class Demo1{
	public static void main(String[] args) {
		String ip = "192.168.10.100";
		try{
			feiQ(ip);  // 如果調用了一個聲明拋出異常類型的方法,那麼調用者必須要處理。
		
		}catch(NoIpException e){
			e.printStackTrace();
			System.out.println("馬上插上網線!");
		}
	}
	public static void feiQ(String ip) throws NoIpException{
		if(ip==null){
			throw new  NoIpException("沒有插網線吧");
		}
		System.out.println("正常顯示好友列表..");
	}
}

運行結果如下圖所示:


④方式一:捕獲處理

class NoIpException extends Exception{//自定義一個沒有網線的異常類
	public NoIpException(String message){
		super(message);  //調用了Exception一個參數的構造函數。
	}

}
class Demo1{
	public static void main(String[] args) {
		String ip = "192.168.10.100";
		ip = null;
		try{
			feiQ(ip);  // 如果調用了一個聲明拋出異常類型的方法,那麼調用者必須要處理。
		
		}catch(NoIpException e){
			e.printStackTrace();
			System.out.println("馬上插上網線!");
		}
	}
	public static void feiQ(String ip) throws NoIpException{
		if(ip==null){
			throw new  NoIpException("沒有插網線吧");
		}
		System.out.println("正常顯示好友列表..");
	}
}

運行結果如下圖所示:


如果自定義的異常類中什麼都不寫,別人會不太明白你的這個異常類是用來描述什麼不正常情況的,如果我們在自定義異常類中加一個字符串,對這個異常進行說明,別人就可以根據這個字符串判斷出你的這個異常類是用來幹嘛的。

⑤方式二:拋出處理

main方法中向外再拋出異常拋給Jvm。

class NoIpException extends Exception{
	public NoIpException(String message){
		super(message);  //調用了Exception一個參數的構造函數。
	}

}
class Demo1{
	public static void main(String[] args) throws NoIpException{
		String ip = "192.168.10.100";
		ip = null;
		feiQ(ip);  
	}
	public static void feiQ(String ip) throws NoIpException{
		if(ip==null){
			throw new  NoIpException("沒有插網線吧");
		}
		System.out.println("正常顯示好友列表..");
	}
}

運行結果如下圖所示:


(2) 實例二:

①需求:

模擬去吃木桶飯,如果帶錢少於了10塊,那麼就拋出一個沒有帶夠錢的異常對象,如果帶夠了,那麼就可以吃上香噴噴的木桶飯.

②實例:

//定義沒錢的異常
class NoMoneyException extends Exception {
	public NoMoneyException(String message){
		super(message);
	}
}

class Demo1 {
	public static void main(String[] args) {
		try{
			eat(9);

		}catch(NoMoneyException e){
			e.printStackTrace();
			System.out.println("打電話給家人送錢");
		}
	}
	public static void eat(int money) throws NoMoneyException{
		if(money<10){
			throw new NoMoneyException("吃霸王餐");
		}
		System.out.println("吃上了香噴噴的地溝油木桶飯!!");
	}
}

③運行結果如下圖所示:


四.異常的分類:

1.異常體系:

異常體系:

--------| Throwable  所有錯誤或者異常的父類
--------------| Error(錯誤)
--------------| Exception(異常) 異常一般都通過代碼處理 
------------------| 運行時異常: 如果一個方法內部拋出了一個運行時異常,那麼方法上可以聲明也可以不聲明,調用者可以處理也可以不處理。

------------------| 編譯時異常(非運行時異常、受檢異常):  如果一個方法內部拋出了一個編譯時異常對象,那麼方法上就必須要聲明,而且調用者也必須要處理。

2.異常的分類:

(1) 運行時異常: RuntimeException以及RuntimeException子類 都是屬於運行時異常。

(2) 編譯時異常: 除了運行時異常就是編譯時異常。

3.疑問:爲什麼java編譯器會如此嚴格要求編譯時異常,對運行時異常如此寬鬆?

(1) 運行時異常都是可以通過程序員良好的編程習慣去避免,比如分母爲0、強制轉換異常、空指針異常,所以java編譯器就沒有嚴格要求處理運行時異常。

(2) 編譯時異常是我們代碼上無法避免的,比如讀寫文件中的IOException。

4.實例

class Demo2{
	public static void main(String[] args){
		div(4,0);
	}
	public static void div(int a,int b){
		if(b==0){
			throw new ArithmeticException();
		}
		int c = a/b;
		System.out.println("c="+c);
	}
}

運行結果如下圖所示:


五.finally塊

1.finally塊的情景需求:


假設有一個資源文件,有一個程序1對這個文件進行讀取,讀取文件資源,讀完之後繼續保持着和這個文件的鏈接;在讀取的過程中有另外一個程序2,程序2想對文件執行刪除操作,程序2對文件的操作不會成功,因爲程序1在佔用着這個資源文件,也就是說資源文件一旦使用完畢,一定要釋放資源文件,否則其他的程序無法對這個資源文件進行操作。只要使用完畢,就不應該繼續霸佔着這個資源,繼續霸佔這個資源就會導致所有程序都無法使用這個資源文件。那麼一定要執行的代碼應該放在哪裏?假設程序1在讀取文件的過程中,在程序1內部處理數據的過程中出現異常,程序1內部出現異常,那麼程序1肯定要釋放這個資源文件,不管你有沒有讀完,在讀的過程中出現了問題,那麼你也應該把這個資源文件釋放出去。

2.finally塊的使用前提:必須要存在try塊才能使用。

3.finally塊的代碼不管是否發生異常都會執行。

(1) 沒有發生異常的情況下:

①實例:

class Demo1{
	public static void main(String[] args){
		div(4,2);
	}
	public static void div(int a,int b){
		try{
			int c = a/b;
			System.out.println("c="+c);
		}catch(Exception e){
			System.out.println("出了除數爲0的異常……");
		}finally{
			System.out.println("finally塊的代碼執行了……");
		}
	}
}

②運行結果:


(2) 發生異常的情況如下:

①實例:

class Demo2{
	public static void main(String[] args){
		div(4,0);
	}
	public static void div(int a,int b){
		try{
			int c = a/b;
			System.out.println("c="+c);
		}catch(Exception e){
			System.out.println("出現了除數爲0的異常……");
		}finally{
			System.out.println("finally塊的代碼執行了……");
		}
	}
}

②運行結果:


(3) 即使遇到return語句,一旦執行return語句整個方法結束,但是finally塊的代碼依然會執行。

①實例:

class Demo3{
	public static void main(String[] args){
		div(4,0);
	}
	public static void div(int a,int b){
		try{
			if(b==0){
				return;
			}
			int c = a/b;
			System.out.println("c="+c);
		}catch(Exception e){
			System.out.println("出現了除數爲0的異常……");
		}finally{
			System.out.println("finally塊的代碼執行了……");
		}
	}
}

②運行結果:


(4) 即使拋出異常,整個方法也會結束,但是finally塊的代碼仍然會執行。

①實例:

class Demo4{
	public static void main(String[] args){
		div(4,0);
	}
	public static void div(int a,int b){
		try{
			int c = a/b;
			System.out.println("c="+c);
		}catch(Exception e){
			System.out.println("出現了除數爲0的異常……");
			throw e;
		}finally{
			System.out.println("finally塊的代碼執行了……");
		}
	}
}

②運行結果:


4.finally塊的代碼在任何情況下都會執行的,除了jvm退出的情況。

(1) 實例:

class Demo5{
	public static void main(String[] args){
		div(4,0);
	}
	public static void div(int a,int b){
		try{
			if(b==0){
				System.exit(0);//退出Jvm
			}
			int c = a/b;
			System.out.println("c="+c);
		}catch(Exception e){
			System.out.println("出現了除數爲0的異常……");
			throw e;
		}finally{
			System.out.println("finally塊的代碼執行了……");
		}
	}
}

(2) 運行結果:


5.finally非常適合做資源釋放的工作,這樣子可以保證資源文件在任何情況下都會被釋放。

6.finally釋放資源的實例:

import java.io.*;
class Demo1 {
	public static void main(String[] args) {
		FileReader fileReader = null;
		try{
			//找到目標文件
			File file = new File("e:\\a.txt");
			//建立程序與文件的數據通道(讀文件之前必須先建立一個管道確保文件的二進制數據通過管道流入程序中)
			fileReader = new FileReader(file);
			//讀取文件
			char[] buf = new char[1024];
			int length = 0; 
			length = fileReader.read(buf);
			System.out.println("讀取到的內容:"+ new String(buf,0,length));
		}catch(IOException e){
			System.out.println("讀取資源文件失敗....");
		}finally{
			try{
				//關閉資源
				//必須要保證關閉資源的代碼一定要執行,能不能釋放成功是另外一回事。
				fileReader.close();
				System.out.println("釋放資源文件成功....");
			}catch(IOException e){
				System.out.println("釋放資源文件失敗....");
			}
		}
	}
}

運行結果如下圖所示:


7.try塊的三種組合方式:

(1) 方式一:比較適用於有異常要處理,但是沒有資源要釋放的。

try{
	可能發生異常的代碼;
}catch(捕獲的異常類型 變量名){
	處理異常的代碼;
}

(2) 方式二:比較適用於既有異常要處理又要釋放資源的代碼。

try{
	可能發生異常的代碼;
}catch(捕獲的異常類型 變量名){
	處理異常的代碼;
}finally{ 
	釋放資源的代碼;
}

(3) 方式三:比較適用於內部拋出的是運行時異常(沒有catch塊就意味着不需要處理異常),並且有資源要被釋放。這種用法在現實開發中很少見,但是我們要知道這種語法是合法的。

try{
	可能發生異常的代碼;
}finally{ 
	釋放資源的代碼;
}


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