Consider the following test case:
public class Main { static int a = 0; public static void main(String[] args) { try { test(); System.out.println("---"); test2(); } catch(Exception e) { System.out.println(a + ": outer catch"); a++; } } public static void test() { try { throw new Exception(); } catch (Exception e) { System.out.println(a + ": inner catch"); a++; } finally { System.out.println(a + ": finally"); a++; } } public static void test2() throws Exception { try { throw new Exception(); } finally { System.out.println(a + ": finally"); a++; } } }
With output:
0: inner catch 1: finally --- 2: finally 3: outer catch
What's the explanation for why in test()
catch happens before finally while in test2()
it's the other way around?
Yes, finally will be called after the execution of the try or catch code blocks.
So yes, finally is performed last, but only for the try block it's attached to.
In normal case when there is no exception in try block then the finally block is executed after try block. However if an exception occurs then the catch block is executed before finally block.
The finally block on a try / catch / finally will always run — even if you bail early with an exception or a return . This is what makes it so useful; it's the perfect place to put code that needs to run regardless of what happens, like cleanup code for error-prone IO.
The key points are these:
try-(catch)-finally
block, the finally
for that particular try
block is performed lasttry
blocks within another, and each of those nested try
blocks can have their own finally
, which would be performed last for those individual try
blocksSo yes, finally
is performed last, but only for the try
block it's attached to.
So given the following snippet:
try { try { throw null; } finally { System.out.println("Finally (inner)"); } } catch (Throwable e) { System.out.println("Catch (outer)"); }
This prints (as seen on ideone.com):
Finally (inner) Catch (outer)
Observe that:
(inner)
, Finally
is last (whether or not any catch
was successful)Catch (outer)
follows Finally (inner)
, but that's because Finally (inner)
is nested inside another try
block within (outer)
Similarly, the following snippet:
try { try { throw null; } catch (Throwable e) { System.out.println("Catch (inner)"); } finally { System.out.println("Finally (inner)"); throw null; } } catch (Throwable e) { System.out.println("Catch (outer)"); }
This prints (as seen on ideone.com):
Catch (inner) Finally (inner) Catch (outer)
try-catch-finally
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With