首先解释一下try catch finally的用法:
1、try+catch 程序的流程是:运行到try块中,如果有异常抛出,则转到catch块去处理。然后执行catch块后面的语句 2、try+catch+finally 程序的流程是:运行到try块中,如果有异常抛出,则转到catch块,catch块执行完毕后,执行finally块的代码,再执行finally块后面的代码。 如果没有异常抛出,执行完try块,也要去执行finally块的代码。然后执行finally块后面的语句 3、try+finally 程序的流程是:运行到try块中,如果有异常抛出的话,程序转向执行finally块的代码。那末finally块后面的代码还会被执行吗?不会!因为没有处理异常,所以遇到异常后,执行完finally后,方法就已抛出异常的方式退出了。
demo1:
package test.java.example; public class TestCatchException { public TestCatchException() { } boolean testEx1() { boolean ret = true ; try { ret = testEx2(); if (!ret) { return false ; } System.out.println("testEx1, at the end of try" ); } catch (Exception e) { System.out.println("testEx1, catch exception" ); ret = false ; } return ret; } boolean testEx2(){ boolean ret = true ; try { int b = 12 ; int c; for ( int i = 2 ; i >= - 2 ; i--) { c = b / i; System.out.println("i=" + i); } ret = true ; } catch (Exception e) { System.out.println("testEx2, catch exception" ); ret = false ; } return ret; } public static void main(String[] args) { TestCatchException testException1 = new TestCatchException(); try { testException1.testEx1(); } catch (Exception e) { e.printStackTrace(); } } }
执行结果:
i=2 i=1 testEx2, catch exception
原因:在testEx2方法中已经catch住了异常(执行catch方法),即将异常自己处理掉了,然后继续往下执行返回,所以在testEx1中并不会有任何异常出现,也就不会执行catch代码块,而是走try的正常流程,经过if判断直接返回false
demo2:
package test.java.example; public class TestThrowException { public TestThrowException() { } boolean testEx() throws Exception { boolean ret = true ; try { ret = testEx1(); return ret; } catch (Exception e) { System.out.println("testEx, catch exception" ); ret = false ; throw e; } finally { System.out.println("testEx, finally; return value=" + ret); } } boolean testEx1() throws Exception { boolean ret = true ; try { ret = testEx2(); if (!ret) { return false ; } System.out.println("testEx1, at the end of try" ); return ret; } catch (Exception e) { System.out.println("testEx1, catch exception" ); ret = false ; throw e; } finally { System.out.println("testEx1, finally; return value=" + ret); } } boolean testEx2() throws Exception { boolean ret = true ; try { int b = 12 ; int c; for ( int i = 2 ; i >= - 2 ; i--) { c = b / i; System.out.println("i=" + i); } return true ; } catch (Exception e) { System.out.println("testEx2, catch exception" ); ret = false ; throw e; } finally { System.out.println("testEx2, finally; return value=" + ret); } } public static void main(String[] args) { TestThrowException testException1 = new TestThrowException(); try { testException1.testEx(); } catch (Exception e) { e.printStackTrace(); } } }
执行结果:
i=2 i=1 testEx2, catch exception testEx2, finally; return value=false testEx1, catch exception testEx1, finally; return value=false testEx, catch exception testEx, finally; return value=false java.lang.ArithmeticException: / by zero at test.java.example.TestThrowException.testEx2(TestThrowException.java:48) at test.java.example.TestThrowException.testEx1(TestThrowException.java:27) at test.java.example.TestThrowException.testEx(TestThrowException.java:13) at test.java.example.TestThrowException.main(TestThrowException.java:64) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)
原因:在testEx2方法中出现除数为0时会抛出异常,然后由catch捕获到,故执行catch部分,打印并抛出异常,然后执行finally打印信息,由于catch中抛出了异常,所以上层方法将会执行catch部分,即testEx1方法将执行catch部分,之后异常还是会继续往上层抛出,到testEx方法并不会执行返回仍然catch住异常然后抛给main函数的catch,然后打印出来
demo3:
package test.java.example; public class TestException { public TestException() { } boolean testEx() throws Exception { boolean ret = true ; try { ret = testEx1(); } catch (Exception e) { System.out.println("testEx, catch exception" ); ret = false ; throw e; } finally { System.out.println("testEx, finally; return value=" + ret); return ret; } } boolean testEx1() throws Exception { boolean ret = true ; try { ret = testEx2(); if (!ret) { return false ; } System.out.println("testEx1, at the end of try" ); return ret; } catch (Exception e) { System.out.println("testEx1, catch exception" ); ret = false ; throw e; } finally { System.out.println("testEx1, finally; return value=" + ret); return ret; } } boolean testEx2() throws Exception { boolean ret = true ; try { int b = 12 ; int c; for ( int i = 2 ; i >= - 2 ; i--) { c = b / i; System.out.println("i=" + i); } return true ; } catch (Exception e) { System.out.println("testEx2, catch exception" ); ret = false ; throw e; } finally { System.out.println("testEx2, finally; return value=" + ret); return ret; } } public static void main(String[] args) { TestException testException1 = new TestException(); try { testException1.testEx(); } catch (Exception e) { e.printStackTrace(); } } }
执行结果:
i=2 i=1 testEx2, catch exception testEx2, finally; return value=false testEx1, finally; return value=false testEx, finally; return value=false
原因:
(假设方法需要返回值) java 的异常处理中, 在不抛出异常的情况下,程序执行完 try 里面的代码块之后,该方法并不会立即结束,而是继续试图去寻找该方法有没有 finally 的代码块, 如果没有 finally 代码块,整个方法在执行完 try 代码块后返回相应的值来结束整个方法; 如果有 finally 代码块,此时程序执行到 try 代码块里的 return 语句之时并不会立即执行 return,而是先去执行 finally 代码块里的代码, 若 finally 代码块里没有 return 或没有能够终止程序的代码,程序将在执行完 finally 代码块代码之后再返回 try 代码块执行 return 语句来结束整个方法; 若 finally 代码块里有 return 或含有能够终止程序的代码,方法将在执行完 finally 之后被结束,不再跳回 try 代码块执行 return。 在抛出异常的情况下,原理也是和上面的一样的,你把上面说到的 try 换成 catch 去理解就 OK 了 *_*,即catch中无论是返回还是抛出异常,最终返回的均是finally中的结果,除非finally无返回。