关于finally语句什么时候执行,是不是一定执行,网上有很多不同的说法,那今天我们就实验一下,下面会对这些问题分别测试,有问题大家可以分享一下,共同讨论。
finally语句是不是一定会被执行
我做了一下试验,至少有两种情况是不会执行的:
- 如果没有执行到try catch语句就返回了(这个是废话)
 
- 如果try语句块中有System.exit(0),执行到这句时JVM直接被终止了,连JVM都停止了,所有都结束了,当然finally语句也不会被执行到。
 
finally和return谁先执行
finally语句在return语句执行之后return返回之前执行
先上例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
   | 
 
  public class FinallyTest {     int i = 0;
      public int finallyTest() {         try {             System.out.println("run finallTest");             return i += 10;         } catch (Exception e) {             System.out.println("run exception");             return i;         } finally {             System.out.println("run finally");             if (i > 0) {                 System.out.println("b>0, b = " + i);             }         }     }
      public static void main(String[] args) {         FinallyTest test = new FinallyTest();         System.out.println(test.finallyTest());     } }
 
 
  | 
 
运行结果:
1 2 3 4
   | run finallTest run finally b>0, b = 10 10
   | 
 
再来一个:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
   | public class FinallyTest {          public String returnTest(){         System.out.println("tun return");
          return "finish";     }
      public String finallyTest(){         try{             System.out.println("run finallTest");             return returnTest();         }catch (Exception e){             System.out.println("run exception");             return "exception";         }finally {             System.out.println("run finally");         }     }
      public static void main(String[] args) {         FinallyTest test=new FinallyTest();         System.out.println(test.finallyTest());     } }
  | 
 
运行结果:
1 2 3 4
   | run finallTest tun return run finally finish
   | 
 
结论:
以上两个例子说明了:return执行完并没有立即返回,执行finally语句之后才返回结果。
finally中的return会覆盖try中的return
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
   | 
 
  public class FinallyTest2 {     public String finallyTest(){         try{             System.out.println("run finallTest");             return "finish";         }catch (Exception e){             System.out.println("run exception");             return "exception";         }finally {             System.out.println("run finally");             return "finally";         }     }
      public static void main(String[] args) {         FinallyTest2 test=new FinallyTest2();         System.out.println(test.finallyTest());     } }
 
  | 
 
运行结果:
1 2 3
   | run finallTest run finally finally
   | 
 
可以看到try中返回的是finish,finally中返回的是finally,最终返回结果为finally。
finally中是否能改变return的内容?
先看两个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
   | public class FinallyTest3 {
      int returnValue=0;
      public int finallyTest(){         try{             System.out.println("run finallTest");             return returnValue+=10;         }catch (Exception e){             System.out.println("run exception");         }finally {             System.out.println("run finally");             returnValue+=20;         }         return returnValue;     }
      public static void main(String[] args) {         FinallyTest3 test=new FinallyTest3();         System.out.println(test.finallyTest());     }
  }
  | 
 
运行结果:
1 2 3
   | run finallTest run finally 10
   | 
 
我们看到return的值并没有发生变化。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
   | public Map<String,String> finallyTest(){         Map<String,String> result=new HashMap<>();         try{             System.out.println("run finallTest");             result.put("KEY","finish");             return result;         }catch (Exception e){             System.out.println("run exception");         }finally {             System.out.println("run finally");             result.put("KEY","finally");             result = null;         }         return result;     }
      public static void main(String[] args) {         FinallyTest4 test=new FinallyTest4();         Map<String,String> result = test.finallyTest();         System.out.println(result.get("KEY"));     }
  | 
 
运行结果:
1 2 3
   | run finallTest run finally finally
   | 
 
而这个例子,返回的结果发生变化了。
这是说明java对这部分的处理有问题吗?并不是,这个涉及到Java到底是传值还是传址的问题了。简要的说:java只有传值没有传址,这也是为什么result = null这句不起作用。
最后总结:finally块的语句在try或catch中的return语句执行之后返回之前执行且finally里的修改语句可能影响也可能不影响try或catch中 return已经确定的返回值,若finally里也有return语句则覆盖try或catch中的return语句直接返回。