What comes first - finally or catch block?
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++;
}
}
pub开发者_StackOverflow中文版lic 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?
The key points are these:
- In a
try-(catch)-finally
block, thefinally
for that particulartry
block is performed last - You can nest
try
blocks within another, and each of those nestedtry
blocks can have their ownfinally
, which would be performed last for those individualtry
blocks
So 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:
- Within
(inner)
,Finally
is last (whether or not anycatch
was successful) Catch (outer)
followsFinally (inner)
, but that's becauseFinally (inner)
is nested inside anothertry
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)
References
- JLS 14.20.2 Execution of
try-catch-finally
Related questions
- In Java, does return trump finally?
- In Java, is the “finally” block guaranteed to be called (in the main method)?
- Does a finally block always run?
- what happens to finally block in the following cases?
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.
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.
Because the finally
block is always executed right before exiting scope. The sequence of events after calling test2()
is as follows:
- exception is thrown in
test2()
- Since
test2
has nocatch
block, the exception is propagated up to the caller. - Since
test2
has afinally
block, it gets executed before returning from the method. - the
catch
in the main method catches the exception.
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.
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.
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.
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.
精彩评论