java异常处理中的return和throw

如果把return和throw放在一起,直接会提示错误。"Unreachable statement"(无法被执行).

然而finally却可以成功骗过编译器让两者并存(是不是可以算是编译器的一个小bug呢),结果是后执行的会覆盖前者。

finally如果有return会覆盖catch里的throw,同样如果finally里有throw会覆盖catch里的return。

进而如果catch里和finally都有return finally中的return会覆盖catch中的。throw也是如此。

这样就好理解一些了,retrun和throw都是使程序跳出当前的方法,自然就是冲突的。如果非要跳出两次那么后者会覆盖前者。

 
  1. public class T {

  2.  
  3. public T() {

  4.  
  5. }

  6.  
  7. boolean testEx() throws Exception {

  8.  
  9. boolean ret = true;

  10.  
  11. try {

  12.  
  13. ret = testEx1();

  14.  
  15. } catch (Exception e) {

  16.  
  17. System.out.println("testEx, catch exception");

  18.  
  19. ret = false;

  20.  
  21. throw e;

  22.  
  23. } finally {

  24.  
  25. System.out.println("testEx, finally; return value=" + ret);

  26.  
  27. return ret;

  28.  
  29. }

  30.  
  31. }

  32.  
  33. boolean testEx1() throws Exception {

  34.  
  35. boolean ret = true;

  36.  
  37. try {

  38.  
  39. ret = testEx2();

  40.  
  41. if (!ret) {

  42.  
  43. return false;

  44.  
  45. }

  46.  
  47. System.out.println("testEx1, at the end of try");

  48.  
  49. return ret;

  50.  
  51. } catch (Exception e) {

  52.  
  53. System.out.println("testEx1, catch exception");

  54.  
  55. ret = false;

  56.  
  57. throw e;

  58.  
  59. }

  60.  
  61. finally {

  62.  
  63. System.out.println("testEx1, finally; return value=" + ret);

  64.  
  65. return ret;

  66.  
  67. }

  68.  
  69. }

  70.  
  71. boolean testEx2() throws Exception {

  72.  
  73. boolean ret = true;

  74.  
  75. try {

  76.  
  77. int b = 12;

  78.  
  79. int c;

  80.  
  81. for (int i = 2; i >= -2; i--) {

  82.  
  83. c = b / i;

  84.  
  85. System.out.println("i=" + i);

  86.  
  87. }

  88.  
  89. return true;

  90.  
  91. } catch (Exception e) {

  92.  
  93. System.out.println("testEx2, catch exception");

  94.  
  95. ret = false;

  96.  
  97. throw e;

  98.  
  99. }

  100. finally {

  101.  
  102. System.out.println("testEx2, finally; return value=" + ret);

  103.  
  104. //return ret;

  105.  
  106. }

  107. }

  108.  
  109. public static void main(String[] args) {

  110.  
  111. T testException1 = new T();

  112.  
  113. try {

  114.  
  115. testException1.testEx();

  116.  
  117. } catch (Exception e) {

  118.  
  119. e.printStackTrace();

  120.  
  121. }

  122.  
  123. }

  124.  
  125. }

i=2
i=1
testEx2, catch exception
testEx2, finally; return value=false
testEx1, catch exception
testEx1, finally; return value=false
testEx, finally; return value=false

try-catch-finally程序块的执行流程

首先执行的是try语句块中的语句,这时可能会有以下三种情况:

1.              如果try块中所有语句正常执行完毕,那么finally块的居于就会被执行,这时分为以下两种情况:

        如果finally块执行顺利,那么整个try-catch-finally程序块正常完成。

        如果finally块由于原因R突然中止,那么try-catch-finally程序块的结局是“由于原因R突然中止(completes abruptly)”

2.              如果try语句块在执行过程中碰到异常V,这时又分为两种情况进行处理:

        如果异常V能够被与try相应的catch块catch到,那么第一个catch到这个异常的catch块(也是离try最近的一个与异常V匹配的catch块)将被执行;这时就会有两种执行结果:

        如果catch块执行正常,那么finally块将会被执行,这时分为两种情况:

        如果finally块执行顺利,那么整个try-catch-finally程序块正常完成。

        如果finally块由于原因R突然中止,那么try-catch-finally程序块的结局是“由于原因R突然中止(completes abruptly)”

        如果catch块由于原因R突然中止,那么finally模块将被执行,分为两种情况:

        如果如果finally块执行顺利,那么整个try-catch-finally程序块的结局是“由于原因R突然中止(completes abruptly)”。

        如果finally块由于原因S突然中止,那么整个try-catch-finally程序块的结局是“由于原因S突然中止(completes abruptly)”,原因R将被抛弃。

虽然我们在testEx2中使用throw e抛出了异常,但是由于testEx2中有finally块,而finally块的执行结果是complete abruptly的。因为return也是一种导致complete abruptly的原因之一,所以整个try-catch-finally程序块的结果是“complete abruptly”,所以在testEx1中调用testEx2时是捕捉不到testEx1中抛出的那个异常的,而只能将finally中的return 结果获取到。当然这种情况是可以避免的,以testEx2为例:如果你一定要使用finally而且又要将catch中 throw的e在testEx1中被捕获到,那么你去掉testEx2中的finally中的return就可以了。如果将testEx2()中的

 
  1. finally {

  2.  
  3. System.out.println("testEx2, finally; return value=" + ret);

  4.  
  5. //return ret;

  6.  
  7. }

修改为

 
  1. finally {

  2.  
  3. System.out.println("testEx2, finally; return value=" + ret);

  4.  
  5. return ret;

  6.  
  7. }

那么运行结果:

i=2
i=1
testEx2, catch exception
testEx2, finally; return value=false
testEx1, finally; return value=false
testEx, finally; return value=false

try-catch-finally程序块中的return

从上面的try-catch-finally程序块的执行流程以及执行结果一节中可以看出无论try或catch中发生了什么情况,finally都是会被执行的,那么写在try或者catch中的return语句也就不会真正的从该函数中跳出了,它的作用在这种情况下就变成了将控制权(语句流程)转到 finally块中;这种情况下一定要注意返回值的处理。

例如,在try或者catch中return false了,而在finally中又return true,那么这种情况下不要期待你的try或者catch中的return false的返回值false被上级调用函数获取到,上级调用函数能够获取到的只是finally中的返回值,因为try或者catch中的return 语句只是转移控制权的作用。

猜你喜欢

转载自blog.csdn.net/xujingcheng123/article/details/83273346