try catch finally 的用法,你知道多少?最详细、最到位的讲解,配合代码实例讲解,让你轻松掌握和理解

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/jspping/article/details/50340383

废话就不多说了,关于 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 讲解就介绍到这里了,谢谢大家观博!

 


阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页