Java Interview Questions (series) - `finally` keyword
Beware of the F-word! 😈
Brief
The difference between the three Java F-words is one of the interviewers' favourite these days.
In the previous post we covered the final
keyword.
🚀 Today we'll look into the finally
keyword.
Usage
You'll always find it in some relation to the try-catch
structure when you want to run some code even if an exception is thrown or not.
For example, if you do some file management and you encounter an exception, the finally
block can be used to close the resources.
Mind that for this particular case you will probably be better off using try-with-resources.
To sum up, the finally block should be used for clean-up code. ♻️
🚀 Let's see it in action!
Implementation
Classic case:
1️⃣ try
block throws an exception
2️⃣ caught by the catch
block
3️⃣ finally
block triggered
🔷 Try - Catch - Finally
public void tryCatchFinally() {
try {
System.out.println("Try block");
int x = 1;
int y = 0;
int z = x/y;
} catch (ArithmeticException e) {
System.out.println("Catch block");
} finally {
System.out.println("Finally block");
}
}
🔸 Output:
Try block
Catch block
Finally block
Classic case with a twist:
1️⃣ try
block throws an exception
2️⃣ not caught by the catch
block
3️⃣ finally
block still triggered
🔷 Try - Catch (Different exception) - Finally
public void tryCatchFinally() {
try {
System.out.println("Try block");
throw new RuntimeException(); // different from the one in the catch block
} catch (ArithmeticException e) {
System.out.println("Catch block");
} finally {
System.out.println("Finally block");
}
}
🔸 Output:
Try block
Finally block
java.lang.RuntimeException
After seeing this result we can come up to the conclusion that a finally
block can work with a try
block even if catch
is present or not.
🔷 Try - Finally
public void tryFinally() {
try {
System.out.println("Try block");
int x = 1;
int y = 0;
int z = x/y;
} finally {
System.out.println("Finally block");
}
}
🔸 Output:
Try block
Finally block
java.lang.ArithmeticException: / by zero
The finally block is triggered even if there is a value returned by the try block.
🔷 Try (Return) - Finally
public void callTryReturnFinally() {
String returnedValue = tryReturnFinally();
System.out.println(returnedValue);
}
private String tryReturnFinally() {
try {
System.out.println("Try block");
return "Returned from try";
} finally {
System.out.println("Finally block");
}
}
🔸 Output:
Try block
Finally block
Returned from try
The previous case also applies if a value is returned from a catch block.
🔷 Try - Catch (Return) - Finally
public void callTryCatchReturnFinally() {
String returnedValue = tryCatchReturnFinally();
System.out.println(returnedValue);
}
private String tryCatchReturnFinally() {
try {
System.out.println("Try block");
throw new ArithmeticException();
} catch (ArithmeticException exception) {
return "Returned from catch";
} finally {
System.out.println("Finally block");
}
}
🔸 Output:
Try block
Finally block
Returned from catch
❓ Seeing all these options, you might be asking, can I have values returned from a finally
block or even throw an exception?
🫤 Theoretically it's possible, but it's considered an anti-pattern as it alters the method's behaviour.
Meaning that anything returned or thrown from the try
and catch
blocks will be ignored. This is why it should be avoided❗️
🔷 Try (Return) - Finally (Return)
public void callTryReturnFinallyReturn() {
String returnedValue = tryReturnFinallyReturn();
System.out.println(returnedValue);
}
private String tryReturnFinallyReturn() {
try {
System.out.println("Try block");
return "Returned from try";
} finally {
System.out.println("Finally block");
return "Returned from finally";
}
}
🔸 Output:
Try block
Finally block
Returned from finally
🔷 Try (Return) - Finally (Throw)
public void callTryReturnFinallyThrow() {
String returnedValue = tryReturnFinallyThrow();
System.out.println(returnedValue);
}
private String tryReturnFinallyThrow() {
try {
System.out.println("Try block");
return "Returned from try";
} finally {
System.out.println("Finally block");
throw new ArithmeticException();
}
}
🔸 Output:
Try block
Finally block
java.lang.ArithmeticException
Keep in mind that you might do it without knowing it❗️
It can happen if the clean-up code in the finally
block throws an exception.
Bonus
Are there cases when a finally
block isn't getting executed❓
✅ Actually yes!
When executing application stopping statements like System.exit
or Runtime.halt
;
🔷 Try (System.exit) - Finally
public void trySystemExitFinally() {
try {
System.out.println("Try block");
System.exit(1);
} finally {
System.out.println("Finally block");
}
}
🔸 Output:
Try block
Process finished with exit code 1
You can find all the code in the Git repository!
Stay tuned! 🚀