Reputation: 165282
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?
Upvotes: 28
Views: 23253
Reputation: 4497
Although this does not apply to the specific question, it is nice to know that resources are closed before the catch and finally clauses.
@Test
public void test() {
try (AutoCloseable closeable = () -> System.out.println("closeable")) {
throw new Exception("Test");
} catch (Exception ex) {
System.out.println("catch");
} finally {
System.out.println("finally");
}
}
Prints:
closeable
catch
finally
Upvotes: 0
Reputation: 1
Try block is executed first. Catch is executed if there is an exception in try block that needs to be caught. Finally block runs in both the cases whether there is exception or not. If there is return statement inside try block then before returning in try block, finally block gets executed and then return is executed in try block.
Upvotes: 0
Reputation: 2250
Because, finally is the very last code to execute in a try..catch block, regardless of whether an exception was thrown, thrown and then handled, or not thrown at all.
In fact the only time finally will not be called is if the JVM exits before it gets to execute it, or if the thread that is executing the try code is killed or interrupted.
In response to comments: Java Description of finally
Note: If the JVM exits while the try or catch code is being executed,
then the finally block may not execute. Likewise, if the thread executing the try or catch code is interrupted or killed, the finally block may not execute even though the application as a whole continues.
However you are right that a ThreadDeath exception is thrown and I can't find much on the specifics of what seems to be conflicting information from sun. It could be a question in itself.
finally (pardon the pun) @brainimus, if you are in the finally and you throw an exception, then the finally code is being executed, my point was the conditions under which the finally code does not get executed.
Upvotes: 2
Reputation: 81
try - catch and finally are used for avoiding situations when a program may get terminated due to the occurance of unwanted error during the execution of the program.
The following points are important....
1)There is only one try for a block......any number of catch statements for a block and only one finally for a block of statments
2)finally is optional.
3) catch is also optional but if the catch statement is missing then finally must appear.
4) All catches corresponding to the child exceptions must be appearing before a catch for a parent exception..
5) Irrespective of the occurance of the exception the statements present in the finally block are executed always with one exclusion.
i.e. IF a System.out.exit() statement is encountered then the program terminates imediately hence finally can not be executed in such cases.
Note: even there is an return statement appears in try block ...then also the code in finally is executed.
Upvotes: 2
Reputation: 383866
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)
Upvotes: 20
Reputation: 116286
Because the finally
block is always executed right before exiting scope. The sequence of events after calling test2()
is as follows:
test2()
test2
has no catch
block, the exception is propagated up to the caller.test2
has a finally
block, it gets executed before returning from the method.catch
in the main method catches the exception.Upvotes: 4
Reputation: 684
If you replace the functions by the methods' code you get:
public class Main {
static int a = 0;
public static void main(String[] args) {
try {
try {
throw new Exception();
}
catch (Exception e) {
// I catch only the *first* exception thrown
System.out.println(a + ": inner catch");
a++;
// let's go to the finally block
}
finally {
System.out.println(a + ": finally");
a++;
// we go on
}
System.out.println("---");
try {
throw new Exception();
}
finally {
// executed because at the same level
System.out.println(a + ": finally");
a++;
}
}
catch(Exception e) {
// I catch only the *second* exception thrown
System.out.println(a + ": outer catch");
a++;
}
}
The first exception makes the catch block execute, then the first finally block is executed. It is not visible at the outer level because of the first catch block. The second exception is intercepted by the catch block at the outer level, but the finally, located at the inner level, is executed first.
Upvotes: 0
Reputation: 35341
catch comes before finally in the same try-catch-finally scope.
It test2 there is no catch in the try-catch-finally scope of test2 so it does the finally before leaving the scope and falling in the higher catch.
Upvotes: 7
Reputation: 1109152
Because the try
block in test2()
doesn't have a catch
block, only a finally
. The code won't "jump back" to the caller to fall into catch
and then "jump ahead" to the finally
to continue there as you seem to think.
Upvotes: 17