Possible开发者_开发百科 Duplicate:
Does a finally block always run?
I learned that the finally clause of a try catch statement, executes always. But some guy said to me that it is possible to avoid executing it(removing it is not an option).
-Does someone how is that possible?
-Also i am curious in knowing why would someone want to avoid to execute it?
Kill it with an uncaught exception within the finally
block, or kill the overall JVM (which kills the thread, among other things).
There is no good reason to stop the execution of a finally
block except poor design. If it's not supposed to run every time, then don't put it in a finally
block.
Using the below test code, I run two different scenarios to see what happens when killing the Thread
:
- Start the
Thread
andsleep
the main thread for 2 seconds. Within theThread
, pretty much immediately enter thefinally
block and then sleep for 5 seconds. Once the main thread is finished waiting, kill theThread
usingstop
. - Start the
Thread
and sleep 2 seconds. Within theThread
, sleep 5 seconds before entering thefinally
block and then sleep some more within thefinally
to give it a chance to be killed.
In the first case, the result is that the finally
block stops executing.
In the second case, the result is that the finally
block executes completely, and on the Thread
that was stop
ped no less.
Output (note the name of the current thread added for all output):
thread-starting [main]
trying [Thread-0]
catching [Thread-0]
finally-sleeping [Thread-0]
thread-stopped [main]
[main]
thread-starting [main]
trying-sleeping [Thread-1]
thread-stopped [main]
finally-sleeping [Thread-1]
finally-done [Thread-1]
Code:
public class Main
{
public static void main(String[] args)
{
testThread(new TestRunnable());
println("");
testThread(new TestRunnable2());
}
private static void testThread(Runnable runnable)
{
Thread testFinally = new Thread(runnable);
println("thread-starting");
testFinally.start();
try
{
Thread.sleep(2000);
}
catch (InterruptedException e)
{
println("main-interrupted...");
}
testFinally.stop();
println("thread-stopped");
}
private static class TestRunnable implements Runnable
{
@Override
public void run()
{
try
{
println("trying");
throw new IllegalStateException("catching");
}
catch (RuntimeException e)
{
println(e.getMessage());
}
finally
{
println("finally-sleeping");
try
{
Thread.sleep(5000);
}
catch (InterruptedException e)
{
println("finally-interrupted");
}
println("finally-done");
}
}
}
private static class TestRunnable2 implements Runnable
{
@Override
public void run()
{
try
{
println("trying-sleeping");
Thread.sleep(5000);
}
catch (InterruptedException e)
{
println("trying-interrupted");
}
finally
{
println("finally-sleeping");
try
{
Thread.sleep(5000);
}
catch (InterruptedException e)
{
println("finally-interrupted");
}
println("finally-done");
}
}
}
private static void println(String line)
{
System.out.printf("%s [%s]%n", line, Thread.currentThread().getName());
System.out.flush();
}
}
-Does someone how is that possible?
System.exit(0);
-Also i am curious in knowing why would someone want to avoid to execute it?
To answer questions like these and appear smart. ;)
BTW, Thread.stop() doesn't prevent finally
being called.
Thread t = new Thread() {
@Override
public void run() {
try {
System.out.println("Thread start");
Thread.sleep(1000);
System.out.println("Thread end");
} catch (InterruptedException ie) {
System.out.println("Thread Interrupted");
} catch (Error e) {
System.out.println("Thread threw an error " + e);
throw e;
} finally {
System.out.println("Thread finally");
}
}
};
t.start();
t.join(100);
t.stop();
prints
Thread start
Thread threw an error java.lang.ThreadDeath
Thread finally
There's no way of avoiding it, unless something external happens such as the Java Virtual Machine shutting down.
As a general rule you should always assume that a finally block will run. The whole point of it is to ensure that it runs regardless of what happens in the try block - there should be no reason to avoid it!
To your first question i think the only way that comes to my mind is by creating an infinite loop or something.(But it makes no sense at all)
try{
while(true);
}
catch(Exception e) {
}
finally {
//..
}
To your second question, i don't really know why would someone want to do something like that
See this link: https://stackoverflow.com/posts/6228601/edit
I can't think of a good reason that you would want to avoid a finally block. If you really don't want to use this feature, then just don't implement a finally block (at your own risk however).
Killing the JVM would do it, but that's not really an acceptible solution for any production code.
Why is removing a finally block not an option?
精彩评论