try catch finally 的用法,你知道多少?最詳細、最到位的講解,配合代碼實例講解,讓你輕鬆掌握和理解

廢話就不多說了,關於 try catch 相信各位已經不陌生了,但是真正意義上去用它呢,還是有欠缺的,爲什麼這麼說呢?因爲博主也

是在做一個項目的時候遇到了這樣的問題,去看了下 API 纔想起來,於是乎就順便寫了這篇博客分享出來,方便大家觀看和學習以

及理解,等下筆者會按順序講解,以及結合項目模塊案例分析結合的使用,讓大家理解起來更簡單更透徹,而不是一大堆的字,看

起來眼睛都花了,好了我們先按順序來

 

① 都帶 return 的情況(程序正常運行的情況下)

 

    public static void main(String args[]) {
    	System.out.println("main:"+TryCatchTest());
    }

    static int TryCatchTest(){
    	int value = 10;
    	try {
    		for(int i=10;i<11;i--){
    			if(i>0){
    					value = value-i;
    					System.out.println("for i="+i+" value:"+value);
    			}
    		}
    		System.out.println("---------- try value:"+value);
    		return value;
    	} catch (Exception e) {
    		System.err.println(e.toString()+"\n---------- catch value:"+value);
    		return value;
    	} finally{
    		System.out.println("---------- finally value:"+value);
    		return 7;
    	}
    }


運行結果:

 

 

for i=10 value:0
for i=9 value:-9
for i=8 value:-17
for i=7 value:-24
for i=6 value:-30
for i=5 value:-35
for i=4 value:-39
for i=3 value:-42
for i=2 value:-44
for i=1 value:-45
---------- try value:-45
---------- finally value:-45
main:7

 

 

可以看到程序正常運行情況下的打印,for 執行完之後,value 最後的值是 -45 ,try 裏面 return 的也是 -45 ,之後會走到 finally 

下執行 finally 的代碼 ,如果 finally 裏面寫了 return 程序就會直接返回這個值,所以 main 裏打印的是 finally 的 return 值,下

面我們在來測試 finally 塊不添加 return 的情況,只在裏面寫一些測試代碼段,我們直接看看輸出結果:

 

for i=10 value:0
for i=9 value:-9
for i=8 value:-17
for i=7 value:-24
for i=6 value:-30
for i=5 value:-35
for i=4 value:-39
for i=3 value:-42
for i=2 value:-44
for i=1 value:-45
---------- try value:-45
---------- finally value:-45
main:-45


我把 finally 模塊裏的 return 屏蔽掉了,裏面的 print 執行了,但 main 最終返回的是 try 模塊的 return 值,所以結果就很明顯

 

了,程序運行正常時,如果 finally 添加了 return ,程序就直接 return finally 模塊下的值,且執行 finally 塊的代碼,下面我們繼

續往下走

 

②都帶 return 的情況(程序出現異常的情況下)

 

    public static void main(String args[]) {
    	System.out.println("main:"+TryCatchTest());
    }

    static int TryCatchTest(){
    	int value = 10;
    	try {
    		for(int i=10;i<11;i--){
    			if(i==3){
    			value = value/0;
    		}
    			if(i>0){
    					value = value-i;
    					System.out.println("for i="+i+" value:"+value);
    			}
    		}
    		System.out.println("---------- try value:"+value);
    		return value;
    	} catch (Exception e) {
    		System.err.println(e.toString()+"\n---------- catch value:"+value);
    		return value;
    	} finally{
    		System.out.println("---------- finally value:"+value);
    		return 7;
    	}
    }

 

 

可以看見我在 for 循環裏面模擬了一個 ArithmeticException 的異常,達到我們測試的要求,下面我們繼續往下,先看打印結果

 

for i=10 value:0
for i=9 value:-9
for i=8 value:-17
for i=7 value:-24
for i=6 value:-30
for i=5 value:-35
for i=4 value:-39
java.lang.ArithmeticException: / by zero
---------- catch value:-39
---------- finally value:-39
main:7


博主模擬了 ArithmeticException 異常之後 , for 循環只執行到了 i = 4 ,因爲等於3的時候出現了我模擬的異常,所以程序由 

 

try 模塊直接跳到了 catch 模塊 ,而且 try 模塊的 return 也不會執行,因爲 for 循環在 i = 3的時候出現了異常已經被 catch 模塊

直接捕獲了,這時候的 value 的值是 -39 ,所以 catch 塊下 return 的也是 -39 ,最後在走到 finally 塊,可以看到 finally 打印的

value 的值仍舊是由 try 塊異常導致被 catch 捕獲的值也就是 -39 ,但在 finally 塊有 return ,最終 main 打印的還是 7 ,所以

最終執行的是 finally 的 return ,接着我再把 finally 的 return 註釋掉,我們繼續看打印結果,並且分析和總結

 

for i=10 value:0
for i=9 value:-9
for i=8 value:-17
for i=7 value:-24
for i=6 value:-30
for i=5 value:-35
for i=4 value:-39
java.lang.ArithmeticException: / by zero
---------- catch value:-39
---------- finally value:-39
main:-39


博主註釋掉 finally 塊的 return 語句之後,finally return 語句之前的代碼仍舊執行了,但最終 return 的是由 catch 捕獲的 try 

 

塊的異常 value 值 -39 ,看到這裏,相信大家都已經明白了吧?就是程序不管異常與否,最終都會執行 finally 裏面的代碼,如果

finally 塊裏面有 return 語句,默認返回 finally 塊 return 的值,如果去掉 finally 的 return 語句,程序最終返回的值由程序的異

常與否決定,比如程序正常,由 try 決定,程序意外出現異常,將由 catch 的返回值決定

 

倘若,try catch finally 都沒有 return 語句,就根據函數的返回值而定(排除 finally 塊添加了return 語句),比如程序的方法返回

一個 int 值,如果正常,最終返回  try 裏面被賦予值的 int 變量,反之異常則由 catch 決定,你可以在 catch 塊獲取此 int 值,或

者做一些你自己想要處理的邏輯

 

看到這裏之後你對 try catch finally 到底掌握了多少呢?別急,下面我將結合一個實例來講一講,怎麼合理運用它們,上實例

 

 

	class PosterAsyncTask extends AsyncTask<String, Integer, List<InputStream>> {

		@Override
		protected void onPreExecute() {
			super.onPreExecute();
		}

		@Override
		protected List<InputStream> doInBackground(String... params) {

			List<InputStream> inputStream = new ArrayList<InputStream>();
			if (mUrl_List.size() > 0) {

				try {
					for (int i = 0; i < mUrl_List.size(); i++) {
						HttpGet httpRequest = new HttpGet(mUrl_List.get(i));
						HttpClient httpclient = new DefaultHttpClient();
						HttpResponse response = (HttpResponse) httpclient
								.execute(httpRequest);
						if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
							HttpEntity entity = response.getEntity();
							BufferedHttpEntity bufferedHttpEntity = new BufferedHttpEntity(
									entity);
							InputStream is = bufferedHttpEntity.getContent();
							if (null != is && i != 0) {
								inputStream.add(is);
							} else {
								String path = mUrl_List.get(0).substring(
										mUrl_List.get(0).lastIndexOf("/") + 1,
										mUrl_List.get(0).length());
								Log.e(TAG, "writer mp3 file... " + path);
								// writeBuffer(is, path);
							}
						}
					}
				} catch (IOException e) {
					e.printStackTrace();
				} finally {
					if (mUrl_List.size() == 0) {
						httpClient.getConnectionManager().shutdown();
					}
				}
			}
			return inputStream;

		}

		@Override
		protected void onProgressUpdate(Integer... values) {
			super.onProgressUpdate(values);
		}

		@Override
		protected void onPostExecute(final List<InputStream> result) {
			super.onPostExecute(result);

			if (result.size() > 0) {
				Message msg = mHandler.obtainMessage();
				msg.obj = result;
				msg.what = 3;
				mHandler.sendMessage(msg);
			}
		}
	}


    

 

PoterAsynTask 是一個下載廣告推送文件的異步操作,就是程序被動或主動響應來自服務器的廣告推送請求,在客戶端需要輪播

展示這個廣告圖片組,且播放背景音樂,這些我們先撇開,直接說異步裏的 try catch finally 相關操作

 

在 PoterAsynTask  被執行,筆者在 doInBackground(String... params)  new 了一個 List<InputStream> 集合來獲取異步下載

成功之後的流,寫入文件我們就忽略了,直接卻入主題吧,首先我們來考慮下正常情況

 

正常情況下,上述代碼會把所有下載完的流存入到 List 集合,然後執行 finally 塊的代碼,finally 塊是關閉了httpClient ,正常情

況下這樣寫一點沒錯,結果會由 onPostExecute(final List<InputStream> result) 並且通過 Handler 發

給 handleMessage(android.os.Message msg) ,然後我執行了如下操作:

 

			if (minputStream.size() > 0) {
				for (InputStream inputStream : minputStream) {
					mBitmapMap
							.put(key, BitmapFactory.decodeStream(inputStream));
					key++;
				}
			}


取流轉Bitmap 存緩存,這裏就不考慮本地緩存了,因爲它不是我們博客要講的東西,這個先不管,繼續剛纔的,如果我

 

在 doInBackground(String... params) 執行下載的時候,突然網絡斷了或者服務器錯誤又或者網絡超時了呢?這時候你要幹得事

情就不是剛剛那些了,因爲那樣會出現各種錯誤,因爲文件壓根就是不完整的,程序異常的話,會走到 catch 下,那麼問題來

了,你可以在 catch 下設置一個標誌位,在 finally 下判斷這個標誌位,比如如果標誌位爲 true 代表程序正常運行完畢,則關閉

httpclient ,false 則不關閉,然後在某處寫一個循環獲取或者被動獲取網絡狀態的函數,保存之前斷掉的字節位,網絡正常了就

繼續進行下載,前提是你要寫文件或者存數據庫保存上一次斷掉的位置,然後繼續寫文件,當然這只是我舉例的一種例子,具體

操作還是要根據需求或者其他因素來決定的

本篇的 try catch finally 講解就介紹到這裏了,謝謝大家觀博!

 

 

發佈了96 篇原創文章 · 獲贊 284 · 訪問量 36萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章