finally
Back to the building. Whenever someone leaves a floor, calmly after work, because of the alarm or ahead of time, the door closes behind them. It always closes, however the person left.
A program also has code that must run whatever happens: close a file, drop a connection, print a report. Put it at the end of try, and an exception may skip it. Put it after catch, and it gets skipped by an exception that this catch does not catch. For such code try has a third block, finally:
public class Main {
public static void main(String[] args) {
int[] boxes = {2, 0};
for (int n : boxes) {
try {
System.out.println(8 / n);
} catch (ArithmeticException e) {
System.out.println("zero");
} finally {
System.out.println("door closed");
}
}
}
}The program prints:
4
door closed
zero
door closedThree ways out of try
The finally block is written after all the catch blocks. It runs last, however try ended. try has three ways out.
No exception
try runs to the end, catch is skipped, then finally runs. With n equal to 2, the program prints 4, and then door closed.
The exception is caught
try breaks off at the line with the exception, the matching catch runs, and finally after it. With n equal to 0, it prints zero, and then door closed again.
No one catches the exception
There is no matching catch, or no catch at all: try can be written with finally alone. Then finally runs anyway, and after it the exception goes on its way to the calling method.
finally and return
The door also closes when a method leaves early through return:
public class Main {
static int share(int n) {
try {
return 10 / n;
} finally {
System.out.println("door closed");
}
}
public static void main(String[] args) {
System.out.println(share(2));
System.out.println(share(0));
}
}door closed
5
door closed
Exception in thread "main" java.lang.ArithmeticException: / by zeroLet's go through it step by step:
share(2)computes10 / 2forreturn. But before the method returns5,finallyruns and printsdoor closed.maingets5and prints it.share(0): the division throws an exception. There is nocatch, butfinallystill printsdoor closed.- The exception leaves
shareformain, no one catches it there either, and the program stops.
This is a classic interview question: does finally run if try has a return? Yes. The value for return is already computed, then finally runs, and only then does the method return the result. finally does not run if the JVM itself stops: for example, if the computer is switched off.
Here the door picture is imprecise. In a building the door closes when you are already out. But finally runs while the method has not finished yet: main is waiting for its 5, and meanwhile share prints door closed.
Common mistake
Code that must always run was placed after try and catch instead of in finally:
String s = "0";
try {
System.out.println(10 / Integer.parseInt(s));
} catch (NumberFormatException e) {
System.out.println("not a number");
}
System.out.println("door closed"); // ✗Exception in thread "main" java.lang.ArithmeticException: / by zeroThe string "0" can be read, but you cannot divide by zero. The catch catches only a NumberFormatException, so the ArithmeticException goes further, and the line after try does not run: the door was left open. Move that line into a finally block after catch. Then door closed is printed here too, before the program stops.
Key points
finallyruns aftertryandcatchwhatever happens: with no exception, with a caught one and with an uncaught one.- If
tryhas areturn,finallyruns before the method returns its value. - An uncaught exception passes through
finallyand goes on to the calling method. - Code that must always run goes into
finally, not aftertry.