Explain Codes LogoExplain Codes Logo

Does a finally block run even if you throw a new Exception?

java
try-catch
finally-block
exception-handling
Alex KataevbyAlex KataevΒ·Feb 5, 2025
⚑TLDR

Yes, the finally block executes, even if a new Exception is thrown within the try or catch blocks. This guarantees actions such as resource release or crucial cleanup operations always run.

try { // Party time! πŸŽ‰ But this might cause an exception throw new Exception(); } catch (Exception e) { // Uh-oh, police! πŸš“ Let's throw another party...I mean exception. throw new Exception(); } finally { // Despite the parties (exceptions), time to clean up System.out.println("Resources released, we're safe!"); }

Regardless of any exceptions thrown, "Resources released, we're safe!" will be printed, which underscores the sheer resilience of the finally block.

When finally doesn't run: The edge cases

Even though the finally block is impressively reliable, it can't outperform a JVM shutdown. So, if System.exit() is invoked or if the processing thread is unexpectedly interrupted, the finally block might be skipped. Unfortunate hardware issues causing the JVM to crash will also render the finally block useless.

Best practices for utilizing finally

Remember that a finally block is like the janitor of your code. It's designed to clean up resources, not to host hefty pieces of crucial logic. It's like expecting your broom to cook dinner β€” not going to happen!

Embedding significant logic in the finally block can lead to unreliable behavior β€” especially dangerous if an uncaught Exception is thrown within it.

Your critical logic should stay cozy and safe outside the try-catch structure, like this:

// This is the precious logic ring, it goes to Mordor before try-catch land! someCriticalOperation(); try { // The potentially perilous journey } catch (Exception e) { // The orc-exception encounter } finally { // Clean up operation (not the logic ring!) }

Also, be careful with trace statements like System.out.println(). Doing in it try-catch can be tricky as it may occasionally disguise the true nature of your program's execution flow:

try { // Code that might cause an Exception // (It's like inviting a bull to a china shop) } catch (Exception e) { System.out.println("Moo!...I mean, Exception caught!"); } finally { System.out.println("Phew, finally reckoned with the bull in the shop!"); // Cleanup code }

Re-throwing exceptions: A double-edged sword

Understanding the ripple effect of re-throwing exceptions on your code's control flow is critical. After a re-throw in your catch block, code that follows β€” including other catch blocksβ€” stays ignored. How rude! But, the finally block still gets its fair chance to perform its sweeping job:

try { // Code that might invite an unexpected guest } catch (IOException e) { throw new RuntimeException(e); // Sending another invite! } finally { // The housekeeper, always on the job! }

Variables in finally: A memory exercise

Note that variables set within a finally block remember their value, unless an exception ensues:

boolean someVar = false; try { // Herding cats can cause an exception } catch (Exception e) { // Well, one ran away } finally { someVar = true; // True unless a wild cat or a JVM issue scares it away }

This predictable behaviour can carry significant weight when managing application state across exception handling.