3 min read

Java Interview Questions (series) - `finally` keyword

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!


💡
Don't miss out on more posts like this! Susbcribe to our free newsletter!
💡
Currently I am working on a Java Interview e-book designed to successfully get you through any Java technical interview you may take.
Stay tuned! 🚀