Finally block execution in Java

Basic Syntax and Behavior

public class FinallyExample { public static void main(String[] args) { try { System.out.println("Inside try block"); int result = 10 / 2; // No exception System.out.println("Result: " + result); } catch (ArithmeticException e) { System.out.println("Exception caught: " + e.getMessage()); } finally { System.out.println("Finally block executed - always runs!"); } } }

Output:

Inside try block Result: 5 Finally block executed - always runs!

Finally with Exception

public class FinallyWithException { public static void main(String[] args) { try { System.out.println("Inside try block"); int result = 10 / 0; // ArithmeticException System.out.println("This won't be printed"); } catch (ArithmeticException e) { System.out.println("Exception caught: " + e.getMessage()); } finally { System.out.println("Finally block executed despite exception!"); } } }

Output:

Inside try block Exception caught: / by zero Finally block executed despite exception!

Finally with Uncaught Exception

public class FinallyUncaughtException { public static void main(String[] args) { try { System.out.println("Inside try block"); String str = null; str.length(); // NullPointerException } catch (ArithmeticException e) { System.out.println("This won't catch NullPointerException"); } finally { System.out.println("Finally executes even with uncaught exception!"); } // This line won't be reached due to uncaught exception } }

Output:

Inside try block Finally executes even with uncaught exception! Exception in thread "main" java.lang.NullPointerException

Return Statement in Finally

public class FinallyReturn { public static int testFinallyReturn() { try { System.out.println("Inside try"); return 1; } finally { System.out.println("Inside finally"); return 2; // This overrides the try return! } } public static void main(String[] args) { System.out.println("Return value: " + testFinallyReturn()); } }

Output:

Inside try Inside finally Return value: 2

System.exit() in Finally

public class FinallySystemExit { public static void testSystemExit() { try { System.out.println("Inside try"); System.exit(0); // JVM terminates here } finally { System.out.println("This won't be printed!"); } } public static void main(String[] args) { testSystemExit(); System.out.println("This also won't be printed"); } }

Output:

Inside try

Real-World Use Cases

1. Resource Cleanup

import java.io.*; public class ResourceCleanup { public static void readFile(String filename) { BufferedReader reader = null; try { reader = new BufferedReader(new FileReader(filename)); String line; while ((line = reader.readLine()) != null) { System.out.println(line); } } catch (IOException e) { System.out.println("Error reading file: " + e.getMessage()); } finally { try { if (reader != null) { reader.close(); System.out.println("File closed successfully"); } } catch (IOException e) { System.out.println("Error closing file: " + e.getMessage()); } } } }

2. Database Connection Cleanup

public class DatabaseExample { public static void processDatabase() { Connection conn = null; PreparedStatement stmt = null; try { // Get database connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "user", "pass"); stmt = conn.prepareStatement("SELECT * FROM users"); // Execute query and process results ResultSet rs = stmt.executeQuery(); while (rs.next()) { // Process each row } } catch (SQLException e) { System.out.println("Database error: " + e.getMessage()); } finally { // Always close resources try { if (stmt != null) stmt.close(); if (conn != null) conn.close(); System.out.println("Database resources closed"); } catch (SQLException e) { System.out.println("Error closing resources: " + e.getMessage()); } } } }

Try-with-Resources (Java 7+)

import java.io.*; public class TryWithResources { public static void readFileModern(String filename) { // Automatic resource management - no finally needed for closing try (BufferedReader reader = new BufferedReader(new FileReader(filename))) { String line; while ((line = reader.readLine()) != null) { System.out.println(line); } } catch (IOException e) { System.out.println("Error: " + e.getMessage()); } // Resources automatically closed here } }

Complex Scenarios

Nested Finally Blocks

public class NestedFinally { public static void complexOperation() { try { System.out.println("Outer try"); try { System.out.println("Inner try"); int result = 10 / 0; } catch (ArithmeticException e) { System.out.println("Inner catch"); throw e; // Re-throw exception } finally { System.out.println("Inner finally"); } } catch (Exception e) { System.out.println("Outer catch: " + e.getMessage()); } finally { System.out.println("Outer finally"); } } public static void main(String[] args) { complexOperation(); } }

Output:

Outer try Inner try Inner catch Inner finally Outer catch: / by zero Outer finally

Important Rules and Behaviors

1. Execution Order

public class ExecutionOrder { public static String testOrder() { try { System.out.println("Try block"); return "Try return"; } catch (Exception e) { System.out.println("Catch block"); return "Catch return"; } finally { System.out.println("Finally block"); // If you return here, it overrides previous returns } } public static void main(String[] args) { System.out.println("Result: " + testOrder()); } }

Output:

Try block Finally block Result: Try return

2. Exception in Finally Block

public class ExceptionInFinally { public static void testFinallyException() { try { try { System.out.println("Inner try"); throw new RuntimeException("Exception from try"); } finally { System.out.println("Inner finally"); throw new RuntimeException("Exception from finally"); } } catch (RuntimeException e) { System.out.println("Caught: " + e.getMessage()); } } public static void main(String[] args) { testFinallyException(); } }

Output:

Inner try Inner finally Caught: Exception from finally

Best Practices

  1. Use finally for cleanup - Always close resources in finally blocks
  2. Avoid returns in finally - They can suppress exceptions from try/catch
  3. Keep finally blocks simple - Avoid complex logic that might throw exceptions
  4. Use try-with-resources - For automatic resource management when possible
  5. Handle exceptions in finally - Wrap resource cleanup in try-catch within finally
// ✅ Good practice public static void safeResourceUsage() { Connection conn = null; try { conn = getConnection(); // Use connection } catch (SQLException e) { // Handle exception } finally { if (conn != null) { try { conn.close(); } catch (SQLException e) { // Log but don't throw - don't mask original exception System.err.println("Warning: Failed to close connection: " + e.getMessage()); } } } }

The finally block is crucial for ensuring that cleanup code always executes, regardless of what happens in the try-catch blocks, making it essential for robust resource management and preventing resource leaks.

Leave a Reply

Your email address will not be published. Required fields are marked *


Macro Nepal Helper