try-catch-finally的使用
2015-08-03 12:03
417 查看
try-catch-finally语句与return联合使用、try-catch对程序性能的影响。我做了九个对比小实验进行研究,得到以下结论:
**1、finally语句在return语句执行之后return返回之前执行的。
2、finally块中的return语句会覆盖try块中的return返回。
3、如果finally语句中没有return语句覆盖返回值,那么原来的返回值可能因为finally里的修改而改变也可能不变。如果返回基本数据类型不会受finally中的修改影响,如果是返回引用类型会受finally中的修改影响。
4、try块里的return语句在异常的情况下不会被执行,这样具体返回哪个看情况。
5、当发生异常后,catch中的return执行情况与未发生异常时try中return的执行情况完全一样。
6、无异常时候,try-catch几乎不影响程序运行时间。
7、有异常的时候,异常类型匹配越精确越少时间开销。
8、不单纯的用Exception过滤异常、尽量少地在try里面添加代码、尽量不在循环里使用try-catch**
实验只是对try-catch-finally的初步认识,如果深入原理研究还需要研究程序字节码。
第一个问题:finally语句是否一定会执行?
答案:不一定
有两种情况:(1)try之前程序就返回了 (2)try之前程序出错,导致无法向下执行。
代码清单一:
Output:
first case:return value is:0
second case:报错
以上两种情况,finally语句都没有得到执行。只有与finally相对应的try语句得到执行的时候finally才会执行。
第二个问题:try语句块得到执行的情况下,finally语句一定会得到执行?
答案:否定
代码清单二:
Output:
previous statement
try
当一个线程在执行 try 语句块或者 catch 语句块时被打断(interrupted)或者被终止(killed),与其相对应的 finally 语句块可能不会执行。还有更极端的情况,就是在线程运行 try 语句块或者 catch 语句块时,突然死机或者断电,finally 语句块肯定不会执行了。
第三个问题:多catch如何匹配捕获
答案:按代码书写顺序寻找最接近的异常进行匹配,找到之后不再进行查找。
代码清单三:
Output:
throw a myException
first catch get it
program is end
throw a Exception
second catch get it
program is end
注意:
1、try块中,抛出异常的语句之后的语句不会得到执行。
2、Catch顺序应该是由派生到基类,由小到大捕获,Exception应该最后捕获。
3、会被最接近的异常类型捕获,一旦异常被捕获,其他catch就不会被执行。
第四个问题:finally语句和return语句执行顺序
答案:finally语句在return语句执行之后返回之前执行
在这里系统的讨论下return在try-catch-finally各语句块中的情况。
情况1: try-catch 中的return
代码清单四:
Output:
g()
1
如果去掉注释输出就是4,如果注释catch当中的return就会报错,因为编译器认为try里面的return之前可能有异常产生,导致return得不到执行,所以要在函数finally或者函数尾部添加return,或者try-catch里同时添加return
情况2:try-finally中的return
代码清单五:
Output:
g()
8
3
如果在finally中也添加return,那么输出为
g()
8
8
finally中无return时,程序会执行了try块中的return之后,缓存结果,然后执行finally块,最后返回缓存的结果,即使finally中对i进行了修改也没有不会反应到返回值中。如果finally里也有return的话,那么直接在finally里返回值,不在返回缓存结果。
情况3:try-catch-finally中都有return
代码清单六:
Output:
catch:4
finally:9
4
如果在finally中添加return,那么输出为
catch:4
finally:9
9
类似于try-catch中return的情况,会缓存catch当中的return,如果finally没有return则返回缓存中的i。如果finally中有return,则直接返回。
第五个问题:返回引用的情况下呢?
代码清单七:
Output:
hellotencent
可以看到即使finally中不进行return覆盖也会让finally块中操作反应到myclass
第六个问题:try-catch是否影响性能
情况1:不产生异常的时候
代码清单八:
Output:
不使用try-catch所用时间:1555
使用try-catch所用時間:1556
实验表明在不产生异常的情况下,try-catch不会明显影响程序运行时间。
情况2:产生异常的时候
代码清单九:
Output:
不使用try-catch所用时间:622
使用try-catch Exception所用時間:22394
使用try-catch myException所用時間:2488
使用try-catch mysecondException所用時間:2177
由于多出对异常进行类型匹配以及相关处理操作,try-catch在有异常处理时,的确会消耗很多的运行时间。但是与不使用try-catch在时间上不具备可比性,因为它们是功能上的对比。
通过试验可知,catch到的异常类型越接近发生的异常越节省时间,如果单纯的用Exception去过滤会造成很大的时间开销。同时可以想到,尽量少地在try里面添加代码、尽量不在循环里使用try-catch、尽量精确地匹配异常等优化措施,从而提高性能。
**1、finally语句在return语句执行之后return返回之前执行的。
2、finally块中的return语句会覆盖try块中的return返回。
3、如果finally语句中没有return语句覆盖返回值,那么原来的返回值可能因为finally里的修改而改变也可能不变。如果返回基本数据类型不会受finally中的修改影响,如果是返回引用类型会受finally中的修改影响。
4、try块里的return语句在异常的情况下不会被执行,这样具体返回哪个看情况。
5、当发生异常后,catch中的return执行情况与未发生异常时try中return的执行情况完全一样。
6、无异常时候,try-catch几乎不影响程序运行时间。
7、有异常的时候,异常类型匹配越精确越少时间开销。
8、不单纯的用Exception过滤异常、尽量少地在try里面添加代码、尽量不在循环里使用try-catch**
实验只是对try-catch-finally的初步认识,如果深入原理研究还需要研究程序字节码。
第一个问题:finally语句是否一定会执行?
答案:不一定
有两种情况:(1)try之前程序就返回了 (2)try之前程序出错,导致无法向下执行。
代码清单一:
package trycatchfinallyDEMO; public class FinallyTest { static int test() { int i = 1; if (1 == i) { return 0; //first case } System.out.println("previous statement"); // i /= 0; //second case try { System.out.println("try"); return i; } finally { System.out.println("finally"); } } public static void main(String[] args) { System.out.println("return value is:" + test()); } }
Output:
first case:return value is:0
second case:报错
以上两种情况,finally语句都没有得到执行。只有与finally相对应的try语句得到执行的时候finally才会执行。
第二个问题:try语句块得到执行的情况下,finally语句一定会得到执行?
答案:否定
代码清单二:
package trycatchfinallyDEMO; public class FinallyTest { static int test() { int i = 1; System.out.println("previous statement"); // i /= 0; //second case try { System.out.println("try"); System.exit(0); return i; } finally { System.out.println("finally"); } } public static void main(String[] args) { System.out.println("return value is:" + test()); } }
Output:
previous statement
try
当一个线程在执行 try 语句块或者 catch 语句块时被打断(interrupted)或者被终止(killed),与其相对应的 finally 语句块可能不会执行。还有更极端的情况,就是在线程运行 try 语句块或者 catch 语句块时,突然死机或者断电,finally 语句块肯定不会执行了。
第三个问题:多catch如何匹配捕获
答案:按代码书写顺序寻找最接近的异常进行匹配,找到之后不再进行查找。
代码清单三:
package trycatchfinallyDEMO; public class myException extends Exception { public String toString(){ return "This is myException!"; } } package trycatchfinallyDEMO; public class mulcatch { static void f() throws myException { System.out.println("throw a myException"); throw new myException(); } static void g() throws Exception { System.out.println("throw a Exception"); throw new Exception(); } public static void main(String[] args) { try { f();// f()抛出异常得到处理后,下面的输出和g()不会得到执行。 System.out.println("**********************"); g(); } catch (myException e) { System.out.println("first catch get it"); } catch (Exception e) {// Exception是基类,应该放在最后捕获,放在最一开始会出错。 System.out.println("second catch get it"); } finally { System.out.println("program is end"); } System.out.println("--------------------------------"); try { g(); // 会被最接近的异常类型捕获 System.out.println("**********************"); f(); } catch (myException e) { System.out.println("first catch get it"); } catch (Exception e) {//哪个catch捕获了异常就会由哪个catch处理,其他catch不执行 System.out.println("second catch get it"); } finally { System.out.println("program is end"); } } }
Output:
throw a myException
first catch get it
program is end
throw a Exception
second catch get it
program is end
注意:
1、try块中,抛出异常的语句之后的语句不会得到执行。
2、Catch顺序应该是由派生到基类,由小到大捕获,Exception应该最后捕获。
3、会被最接近的异常类型捕获,一旦异常被捕获,其他catch就不会被执行。
第四个问题:finally语句和return语句执行顺序
答案:finally语句在return语句执行之后返回之前执行
在这里系统的讨论下return在try-catch-finally各语句块中的情况。
情况1: try-catch 中的return
代码清单四:
package trycatchfinallyDEMO; public class tryandcatchwithreturn { static int g(int i) { try { //i /= 0;//此处触发异常之后,就直接执行catch并返回,try里面剩下的语句不再执行。 System.out.println("g()"); return i; } catch (Exception e) { i += 3; return i; } } public static void main(String[] args) { System.out.println(g(1)); } }
Output:
g()
1
如果去掉注释输出就是4,如果注释catch当中的return就会报错,因为编译器认为try里面的return之前可能有异常产生,导致return得不到执行,所以要在函数finally或者函数尾部添加return,或者try-catch里同时添加return
情况2:try-finally中的return
代码清单五:
package trycatchfinallyDEMO; public class tryandfinallywithreturn { static int g(int i) { try { i += 2; System.out.println("g()"); return i; } catch (Exception e) { } finally { i += 5; System.out.println(i); //return i; // finally里也有return,先執行try裏面的return并緩存,然后由于finally里面也有return,所以程序不再返回try进行return // 而是直接在finally进行return } } public static void main(String[] agrs) { System.out.println(g(1)); } }
Output:
g()
8
3
如果在finally中也添加return,那么输出为
g()
8
8
finally中无return时,程序会执行了try块中的return之后,缓存结果,然后执行finally块,最后返回缓存的结果,即使finally中对i进行了修改也没有不会反应到返回值中。如果finally里也有return的话,那么直接在finally里返回值,不在返回缓存结果。
情况3:try-catch-finally中都有return
代码清单六:
package trycatchfinallyDEMO; public class trycatchfinallywithreturn { static int g(int i) { try { i /= 0; System.out.println("g()"); return i; } catch (Exception e) { i += 3; System.out.println("catch:" + i); return i; } finally { i += 5; System.out.println("finally:" + i); //return i;//和try-catch中return的情况一样,会缓存catch当中的return,如果finally没有return则返回缓存中的i //如果finally中有return,则直接返回。 } } public static void main(String[] args) { System.out.println(g(1)); } }
Output:
catch:4
finally:9
4
如果在finally中添加return,那么输出为
catch:4
finally:9
9
类似于try-catch中return的情况,会缓存catch当中的return,如果finally没有return则返回缓存中的i。如果finally中有return,则直接返回。
第五个问题:返回引用的情况下呢?
代码清单七:
package trycatchfinallyDEMO; public class recommenddemo { static myClass myclass = new myClass(); static myClass g() { try { myclass.setTip("world"); return myclass; } catch (Exception e) { myclass.setTip("r u ok?"); return myclass; } finally { myclass.setTip("tencent"); //return myclass; } } public static void main(String[] args) { System.out.println(g()); } }
Output:
hellotencent
可以看到即使finally中不进行return覆盖也会让finally块中操作反应到myclass
第六个问题:try-catch是否影响性能
情况1:不产生异常的时候
代码清单八:
package trycatchfinallyDEMO; public class trycatchPerformance { public static void main(String[] args) { int result = 1; long starttime1 = System.nanoTime(); for (int i = 0; i < 20; i++) { result *= i; } long endtime1 = System.nanoTime(); System.out.println("不使用try-catch所用时间:" + (endtime1 - starttime1)); result = 1; long starttime2 = System.nanoTime(); try { for (int i = 0; i < 20; i++) { result *= i; } } catch (Exception e) { // TODO: handle exception } long endtime2 = System.nanoTime(); System.out.println("使用try-catch所用時間:" + (endtime2 - starttime2)); } }
Output:
不使用try-catch所用时间:1555
使用try-catch所用時間:1556
实验表明在不产生异常的情况下,try-catch不会明显影响程序运行时间。
情况2:产生异常的时候
代码清单九:
package trycatchfinallyDEMO; public class PerformanceWithEception { public static void main(String[] args) { int result = 1; long starttime1 = System.nanoTime(); for (int i = 0; i < 20; i++) { result *= i; } long endtime1 = System.nanoTime(); System.out.println("不使用try-catch所用时间:" + (endtime1 - starttime1)); result = 1; long starttime2 = System.nanoTime(); try { for (int i = 0; i < 20; i++) { result *= i; } throw new mysecondException(); } catch (Exception e) { // TODO: handle exception } long endtime2 = System.nanoTime(); System.out.println("使用try-catch Exception所用時間:" + (endtime2 - starttime2)); long starttime3 = System.nanoTime(); try { for (int i = 0; i < 20; i++) { result *= i; } throw new mysecondException(); } catch (myException e) { // TODO: handle exception }catch (Exception e) { // TODO: handle exception } long endtime3 = System.nanoTime(); System.out.println("使用try-catch myException所用時間:" + (endtime3 - starttime3)); long starttime4 = System.nanoTime(); try { for (int i = 0; i < 20; i++) { result *= i; } throw new mysecondException(); } catch (mysecondException e) { // TODO: handle exception }catch (myException e) { // TODO: handle exception } catch (Exception e) { // TODO: handle exception } long endtime4 = System.nanoTime(); System.out.println("使用try-catch mysecondException所用時間:" + (endtime4 - starttime4)); } }
Output:
不使用try-catch所用时间:622
使用try-catch Exception所用時間:22394
使用try-catch myException所用時間:2488
使用try-catch mysecondException所用時間:2177
由于多出对异常进行类型匹配以及相关处理操作,try-catch在有异常处理时,的确会消耗很多的运行时间。但是与不使用try-catch在时间上不具备可比性,因为它们是功能上的对比。
通过试验可知,catch到的异常类型越接近发生的异常越节省时间,如果单纯的用Exception去过滤会造成很大的时间开销。同时可以想到,尽量少地在try里面添加代码、尽量不在循环里使用try-catch、尽量精确地匹配异常等优化措施,从而提高性能。
相关文章推荐
- 客户端和服务器通讯 方法(2)
- Morris Traversal方法遍历二叉树
- NGUI初探之UIRoot
- Linux - EXT2文件系统
- Linux - EXT2文件系统
- Android 简单sd卡浏览器
- 图论浅析--最小生成树之Kruskal
- 图论浅析--最小生成树之Kruskal
- 背景附件 background-attachment
- 1002 归并排序
- java连接mysql 连接数太多
- MFC学习
- java笔记(一)[static和final常量&String.format()问题&Array类&finalize方法及内存回收]
- 填补新版SDWebImage使用
- PHP使用CURL详解
- NOI2011 阿狸的打字机
- 分布式程序设计
- hadoop权威指南(第四版)要点翻译(2)——Chapter 1. Meet Hadoop
- 完美退出应用程序
- CentOS 7