Try-Catch-Finally
Java 虚拟机会把 finally 语句块作为 subroutine(对于这个 subroutine 不知该如何翻译为好,干脆就不翻译了,免得产生歧义和误解。)直接插入到 try 语句块或者 catch 语句块的控制转移语句之前。但是,还有另外一个不可忽视的因素,那就是在执行 subroutine(也就是 finally 语句块)之前,try 或者 catch 语句块会保留其返回值到本地变量表(Local Variable Table)中。待 subroutine 执行完毕之后,再恢复保留的返回值到操作数栈中,然后通过 return 或者 throw 语句将其返回给该方法的调用者。
例子1
/** finally块的语句在try或catch中的return语句执行之后返回之前执行 */ public class Test1 { public static void main(String[] args) { try { System.out.println("try block"); return; } finally { System.out.println("finally block"); } // #######打印################### // try block // finally block } }
例子2
/**finally块的语句在try或catch中的return语句执行之后返回之前执行*/ public class Test2 { public static void main(String[] args) { System.out.println("reture value of test() : " + test()); // #######打印################### // try block // exception block // finally block // reture value of test() : 2 } public static int test() { int i = 1; try { System.out.println("try block"); i = 1 / 0; return 1; } catch (Exception e) { System.out.println("exception block"); return 2; } finally { System.out.println("finally block"); } } }
例子3
/**finally块的语句在try或catch中的return语句执行之后返回之前执行 * 若finally里也有return语句则覆盖try或catch中的return语句直接返回 * */ public class Test3 { public static void main(String[] args) { System.out.println("return value of getValue(): " + getValue()); // #######打印################### // return value of getValue(): 1 } @SuppressWarnings("finally") public static int getValue() { try { return 0; } finally { return 1; } } }
例子4
/**finally块的语句在try或catch中的return语句执行之后返回之前执行 * 若finally里也有return语句则覆盖try或catch中的return语句直接返回 * */ public class Test4 { public static void main(String[] args) { System.out.println("return value of getValue(): " + getValue()); //return value of getValue(): 1 // #######打印################### // return value of getValue(): 1 } public static int getValue() { int i = 1; try { return i; } finally { i++; } } }
例子5
/**finally块的语句在try或catch中的return语句执行之后返回之前执行*/ public class Test5 { public static void main(String[] args) { System.out.println(test()); // #######打印################### // try block // return statement // finally block // after return } public static String test() { try { System.out.println("try block"); return test1(); } finally { System.out.println("finally block"); } } public static String test1() { System.out.println("return statement"); return "after return"; } }
例子6
/**finally块的语句在try或catch中的return语句执行之后返回之前执行*/ public class Test6 { public static void main(String[] args) { System.out.println(getMap().get("KEY").toString()); // #######打印################### // FINALLY } public static Map<String, String> getMap() { Map<String, String> map = new HashMap<String, String>(); map.put("KEY", "INIT"); try { map.put("KEY", "TRY"); return map; //这时候,本地局部变量表中有个零时变量保存了map的地址了,等finally块执行完后,将其压入操作数栈中返回 } catch (Exception e) { map.put("KEY", "CATCH"); } finally { map.put("KEY", "FINALLY"); map = null; //这里虽然赋值为null了,但是对返回值没有影响 } return map; } }
例子7
/**finally块的语句在try或catch中的return语句执行之后返回之前执行*/ public class Test7 { public static void main(String[] args) { System.out.println(test4()); // #######打印################### // try block // catch block // finally block // b>25, b = 35 // 204 } public static int test4() { int b = 20; try { System.out.println("try block"); b = b / 0; return b += 80; } catch (Exception e) { b += 15; System.out.println("catch block"); } finally { System.out.println("finally block"); if (b > 25) { System.out.println("b>25, b = " + b); } b += 50; } return 204; } }