What’s finally for?
In a language without garbage collection and without automatic destructor calls,[42] finally is important because it allows the programmer to guarantee the release of memory regardless of what happens in the try block. But Java has garbage collection, so releasing memory is virtually never a problem. Also, it has no destructors to call. So when do you need to use finally in Java?
The finally clause is necessary when you need to set something other than memory back to its original state. This is some kind of cleanup like an open file or network connection, something you’ve drawn on the screen, or even a switch in the outside world, as modeled in the following example:
//: c09:Switch.java
public class Switch {
private boolean state = false;
public boolean read() { return state; }
public void on() { state = true; }
public void off() { state = false; }
} ///:~
//: c09:OnOffException1.java
public class OnOffException1 extends Exception {} ///:~
//: c09:OnOffException2.java
public class OnOffException2 extends Exception {} ///:~
//: c09:OnOffSwitch.java
// Why use finally?
public class OnOffSwitch {
private static Switch sw = new Switch();
public static void f()
throws OnOffException1,OnOffException2 {}
public static void main(String[] args) {
try {
sw.on();
// Code that can throw exceptions...
f();
sw.off();
} catch(OnOffException1 e) {
System.err.println("OnOffException1");
sw.off();
} catch(OnOffException2 e) {
System.err.println("OnOffException2");
sw.off();
}
}
} ///:~
The goal here is to make sure that the switch is off when main( ) is completed, so sw.off( ) is placed at the end of the try block and at the end of each exception handler. But it’s possible that an exception could be thrown that isn’t caught here, so sw.off( ) would be missed. However, with finally you can place the cleanup code from a try block in just one place:
//: c09:WithFinally.java
// Finally Guarantees cleanup.
public class WithFinally {
static Switch sw = new Switch();
public static void main(String[] args) {
try {
sw.on();
// Code that can throw exceptions...
OnOffSwitch.f();
} catch(OnOffException1 e) {
System.err.println("OnOffException1");
} catch(OnOffException2 e) {
System.err.println("OnOffException2");
} finally {
sw.off();
}
}
} ///:~
Here the sw.off( ) has been moved to just one place, where it’s guaranteed to run no matter what happens.
Even in cases in which the exception is not caught in the current set of catch clauses, finally will be executed before the exception handling mechanism continues its search for a handler at the next higher level:
//: c09:AlwaysFinally.java
// Finally is always executed.
import com.bruceeckel.simpletest.*;
class FourException extends Exception {}
public class AlwaysFinally {
private static Test monitor = new Test();
public static void main(String[] args) {
System.out.println("Entering first try block");
try {
System.out.println("Entering second try block");
try {
throw new FourException();
} finally {
System.out.println("finally in 2nd try block");
}
} catch(FourException e) {
System.err.println(
"Caught FourException in 1st try block");
} finally {
System.err.println("finally in 1st try block");
}
monitor.expect(new String[] {
"Entering first try block",
"Entering second try block",
"finally in 2nd try block",
"Caught FourException in 1st try block",
"finally in 1st try block"
});
}
} ///:~
The finally statement will also be executed in situations in which break and continue statements are involved. Note that, along with the labeled break and labeled continue, finally eliminates the need for a goto statement in Java.