Introduction
Imagine you're a chef cooking in a kitchen. Sometimes things go wrong—you might burn the food, drop a plate, or run out of ingredients. A good chef has contingency plans: backup ingredients, fire extinguishers, and first aid kits. In Java, try-catch blocks are exactly like these contingency plans—they handle unexpected situations (exceptions) gracefully without crashing your entire program!
Try-catch blocks are Java's mechanism for exception handling. They allow you to write code that might cause errors in a "protected" zone (try block) and then handle those errors gracefully in "recovery" zones (catch blocks).
What are Try-Catch Blocks?
Try-catch blocks are control structures that handle exceptions (runtime errors) in Java. They allow you to separate normal code execution from error handling logic.
Key Characteristics:
- ✅ Try block - Code that might throw exceptions
- ✅ Catch block - Handles specific exceptions
- ✅ Finally block - Always executes (cleanup code)
- ✅ Prevents program crashes - Graceful error recovery
- ✅ Multiple catch blocks - Handle different exception types
Code Explanation with Examples
Example 1: Basic Try-Catch Structure
public class BasicTryCatch { public static void main(String[] args) { System.out.println("=== BASIC TRY-CATCH STRUCTURE ==="); // ❌ DANGEROUS: Code without exception handling // int result = 10 / 0; // This would crash the program! // ✅ SAFE: Code with exception handling try { System.out.println("Starting risky operation..."); int result = 10 / 0; // This will throw ArithmeticException System.out.println("Result: " + result); // This line won't execute } catch (ArithmeticException e) { System.out.println("❌ Error: Cannot divide by zero!"); System.out.println("Exception message: " + e.getMessage()); } System.out.println("Program continues normally after handling exception!"); System.out.println("\n=== SUCCESSFUL OPERATION ==="); try { System.out.println("Starting safe operation..."); int result = 10 / 2; // This works fine System.out.println("Result: " + result); // This line executes } catch (ArithmeticException e) { System.out.println("❌ Error: " + e.getMessage()); // Won't execute } System.out.println("Program continues after successful operation!"); System.out.println("\n=== EXCEPTION OBJECT INFORMATION ==="); try { int[] numbers = {1, 2, 3}; System.out.println("Accessing array: " + numbers[5]); // ArrayIndexOutOfBoundsException } catch (ArrayIndexOutOfBoundsException e) { System.out.println("❌ Array error occurred!"); System.out.println("Message: " + e.getMessage()); System.out.println("Exception type: " + e.getClass().getSimpleName()); System.out.println("Stack trace:"); e.printStackTrace(); // Shows where error occurred } } } Output:
=== BASIC TRY-CATCH STRUCTURE === Starting risky operation... ❌ Error: Cannot divide by zero! Exception message: / by zero Program continues normally after handling exception! === SUCCESSFUL OPERATION === Starting safe operation... Result: 5 Program continues after successful operation! === EXCEPTION OBJECT INFORMATION === ❌ Array error occurred! Message: Index 5 out of bounds for length 3 Exception type: ArrayIndexOutOfBoundsException Stack trace: java.lang.ArrayIndexOutOfBoundsException: Index 5 out of bounds for length 3 at BasicTryCatch.main(BasicTryCatch.java:33)
Example 2: Multiple Catch Blocks
import java.util.InputMismatchException; import java.util.Scanner; public class MultipleCatchBlocks { public static void main(String[] args) { System.out.println("=== MULTIPLE CATCH BLOCKS ==="); Scanner scanner = new Scanner(System.in); // Example 1: Different exceptions in same try block System.out.println("\n=== EXAMPLE 1: DIVISION CALCULATOR ==="); try { System.out.print("Enter numerator: "); int numerator = scanner.nextInt(); System.out.print("Enter denominator: "); int denominator = scanner.nextInt(); int result = numerator / denominator; System.out.println("Result: " + numerator + " / " + denominator + " = " + result); } catch (InputMismatchException e) { System.out.println("❌ Input error: Please enter valid integers!"); scanner.nextLine(); // Clear invalid input } catch (ArithmeticException e) { System.out.println("❌ Math error: " + e.getMessage()); System.out.println("Cannot divide by zero!"); } catch (Exception e) { System.out.println("❌ Unexpected error: " + e.getMessage()); } // Example 2: Array operations with multiple exceptions System.out.println("\n=== EXAMPLE 2: ARRAY OPERATIONS ==="); int[] numbers = {10, 20, 30, 40, 50}; try { System.out.print("Enter array index to access: "); int index = scanner.nextInt(); System.out.print("Enter divisor for calculation: "); int divisor = scanner.nextInt(); int value = numbers[index]; int calculation = value / divisor; System.out.println("Array[" + index + "] = " + value); System.out.println(value + " / " + divisor + " = " + calculation); } catch (ArrayIndexOutOfBoundsException e) { System.out.println("❌ Array index error: " + e.getMessage()); System.out.println("Valid indices are 0 to " + (numbers.length - 1)); } catch (InputMismatchException e) { System.out.println("❌ Input error: Please enter a valid integer!"); scanner.nextLine(); // Clear invalid input } catch (ArithmeticException e) { System.out.println("❌ Math error: " + e.getMessage()); } catch (Exception e) { System.out.println("❌ Unexpected error occurred!"); e.printStackTrace(); } // Example 3: Order matters - specific to general System.out.println("\n=== EXAMPLE 3: CATCH BLOCK ORDER ==="); try { String text = null; System.out.println("Text length: " + text.length()); // NullPointerException } catch (NullPointerException e) { System.out.println("✅ Caught specific exception: NullPointerException"); System.out.println("Message: " + e.getMessage()); } catch (Exception e) { System.out.println("✅ Caught general exception"); System.out.println("This would catch any other exception"); } // ❌ BAD: Wrong order (general before specific) /* try { // some code } catch (Exception e) { // ❌ Too general - catches everything System.out.println("General exception"); } catch (NullPointerException e) { // ❌ Unreachable - compiler error! System.out.println("This will never be executed"); } */ scanner.close(); System.out.println("\n=== PROGRAM COMPLETED SUCCESSFULLY ==="); } public static void demonstrateCatchOrder() { System.out.println("\n=== PROPER CATCH ORDER ==="); System.out.println("Specific exceptions first, then general ones:"); System.out.println("try {"); System.out.println(" // risky code"); System.out.println("} catch (SpecificException e) {"); System.out.println(" // handle specific case"); System.out.println("} catch (AnotherSpecificException e) {"); System.out.println(" // handle another specific case"); System.out.println("} catch (Exception e) {"); System.out.println(" // handle any other exceptions"); System.out.println("}"); } } Output:
=== MULTIPLE CATCH BLOCKS === === EXAMPLE 1: DIVISION CALCULATOR === Enter numerator: abc ❌ Input error: Please enter valid integers! === EXAMPLE 2: ARRAY OPERATIONS === Enter array index to access: 10 ❌ Array index error: Index 10 out of bounds for length 5 Valid indices are 0 to 4 === EXAMPLE 3: CATCH BLOCK ORDER === ✅ Caught specific exception: NullPointerException Message: null === PROGRAM COMPLETED SUCCESSFULLY ===
Example 3: Finally Block and Try-With-Resources
import java.io.*; import java.util.Scanner; public class FinallyAndResources { // Method demonstrating finally block public static void readFileWithFinally(String filename) { FileReader reader = null; System.out.println("\n=== READING FILE WITH FINALLY BLOCK: " + filename + " ==="); try { reader = new FileReader(filename); BufferedReader bufferedReader = new BufferedReader(reader); String line; System.out.println("File contents:"); while ((line = bufferedReader.readLine()) != null) { System.out.println(" " + line); } System.out.println("✅ File read successfully!"); } catch (FileNotFoundException e) { System.out.println("❌ File error: " + e.getMessage()); System.out.println("Please check if the file exists!"); } catch (IOException e) { System.out.println("❌ Reading error: " + e.getMessage()); } finally { // ❌ IMPORTANT: Finally block ALWAYS executes System.out.println("🔒 Finally block executed - cleaning up resources"); if (reader != null) { try { reader.close(); System.out.println("✅ File reader closed successfully"); } catch (IOException e) { System.out.println("❌ Error closing file: " + e.getMessage()); } } } } // Method demonstrating try-with-resources (Java 7+) public static void readFileWithResources(String filename) { System.out.println("\n=== READING FILE WITH TRY-WITH-RESOURCES: " + filename + " ==="); // ✅ try-with-resources automatically closes resources try (FileReader reader = new FileReader(filename); BufferedReader bufferedReader = new BufferedReader(reader)) { System.out.println("File contents:"); String line; while ((line = bufferedReader.readLine()) != null) { System.out.println(" " + line); } System.out.println("✅ File read successfully!"); } catch (FileNotFoundException e) { System.out.println("❌ File error: " + e.getMessage()); } catch (IOException e) { System.out.println("❌ Reading error: " + e.getMessage()); } // No finally block needed - resources automatically closed! } // Method demonstrating finally block behavior public static void demonstrateFinallyBehavior() { System.out.println("\n=== FINALLY BLOCK BEHAVIOR ==="); // Case 1: No exception System.out.println("Case 1: No exception"); try { System.out.println(" Try block executed"); } catch (Exception e) { System.out.println(" Catch block executed"); } finally { System.out.println(" ✅ Finally block executed"); } // Case 2: Exception caught System.out.println("\nCase 2: Exception caught"); try { System.out.println(" Try block executed"); throw new RuntimeException("Test exception"); } catch (Exception e) { System.out.println(" ✅ Catch block executed: " + e.getMessage()); } finally { System.out.println(" ✅ Finally block executed"); } // Case 3: Exception not caught System.out.println("\nCase 3: Exception not caught (different type)"); try { System.out.println(" Try block executed"); throw new RuntimeException("Uncaught exception"); } catch (NullPointerException e) { // Wrong exception type System.out.println(" Catch block executed"); } finally { System.out.println(" ✅ Finally block executed even with uncaught exception!"); } // Case 4: Return in try block System.out.println("\nCase 4: Return statement in try block"); String result = testReturnInTry(); System.out.println(" Method returned: " + result); } public static String testReturnInTry() { try { System.out.println(" Try block with return statement"); return "Return value from try"; } catch (Exception e) { System.out.println(" Catch block executed"); return "Return value from catch"; } finally { System.out.println(" ✅ Finally block executed after return!"); // Note: You can't change the return value in finally } } // Custom resource that implements AutoCloseable static class DatabaseConnection implements AutoCloseable { private String connectionId; public DatabaseConnection(String id) { this.connectionId = id; System.out.println("🔗 Database connection opened: " + connectionId); } public void executeQuery(String query) { System.out.println("📊 Executing query on " + connectionId + ": " + query); } @Override public void close() { System.out.println("🔒 Database connection closed: " + connectionId); } } public static void demonstrateAutoCloseable() { System.out.println("\n=== AUTOCLOSEABLE RESOURCES ==="); // Using custom AutoCloseable resource try (DatabaseConnection db = new DatabaseConnection("DB-001")) { db.executeQuery("SELECT * FROM users"); db.executeQuery("UPDATE settings SET value = 'new'"); // No need to manually close - automatically called } catch (Exception e) { System.out.println("❌ Database error: " + e.getMessage()); } // Resources automatically closed even if exception occurs System.out.println("Program continues after database operations"); } public static void main(String[] args) { System.out.println("=== FINALLY BLOCK AND TRY-WITH-RESOURCES ==="); // Create a test file first createTestFile("test.txt"); // Demonstrate finally block readFileWithFinally("test.txt"); readFileWithFinally("nonexistent.txt"); // This will cause error // Demonstrate try-with-resources readFileWithResources("test.txt"); readFileWithResources("nonexistent.txt"); // This will cause error // Demonstrate finally behavior demonstrateFinallyBehavior(); // Demonstrate AutoCloseable demonstrateAutoCloseable(); // Clean up deleteTestFile("test.txt"); } private static void createTestFile(String filename) { try (PrintWriter writer = new PrintWriter(new FileWriter(filename))) { writer.println("Hello World!"); writer.println("This is a test file."); writer.println("Java Exception Handling Demo"); } catch (IOException e) { System.out.println("Error creating test file: " + e.getMessage()); } } private static void deleteTestFile(String filename) { File file = new File(filename); if (file.exists()) { file.delete(); } } } Output:
=== FINALLY BLOCK AND TRY-WITH-RESOURCES === === READING FILE WITH FINALLY BLOCK: test.txt === File contents: Hello World! This is a test file. Java Exception Handling Demo ✅ File read successfully! 🔒 Finally block executed - cleaning up resources ✅ File reader closed successfully === READING FILE WITH FINALLY BLOCK: nonexistent.txt === ❌ File error: nonexistent.txt (No such file or directory) Please check if the file exists! 🔒 Finally block executed - cleaning up resources === READING FILE WITH TRY-WITH-RESOURCES: test.txt === File contents: Hello World! This is a test file. Java Exception Handling Demo ✅ File read successfully! === READING FILE WITH TRY-WITH-RESOURCES: nonexistent.txt === ❌ File error: nonexistent.txt (No such file or directory) === FINALLY BLOCK BEHAVIOR === Case 1: No exception Try block executed ✅ Finally block executed Case 2: Exception caught Try block executed ✅ Catch block executed: Test exception ✅ Finally block executed Case 3: Exception not caught (different type) Try block executed ✅ Finally block executed even with uncaught exception! Case 4: Return statement in try block Try block with return statement ✅ Finally block executed after return! Method returned: Return value from try === AUTOCLOSEABLE RESOURCES === 🔗 Database connection opened: DB-001 📊 Executing query on DB-001: SELECT * FROM users 📊 Executing query on DB-001: UPDATE settings SET value = 'new' 🔒 Database connection closed: DB-001 Program continues after database operations
Example 4: Real-World Exception Handling Scenarios
import java.net.URL; import java.net.MalformedURLException; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; public class RealWorldScenarios { // Scenario 1: User input validation public static void validateUserRegistration(String username, String email, String ageStr) { System.out.println("\n=== USER REGISTRATION VALIDATION ==="); System.out.println("Username: " + username); System.out.println("Email: " + email); System.out.println("Age: " + ageStr); try { // Validate username if (username == null || username.trim().isEmpty()) { throw new IllegalArgumentException("Username cannot be empty"); } if (username.length() < 3) { throw new IllegalArgumentException("Username must be at least 3 characters"); } // Validate email using regex validateEmail(email); // Validate age int age = Integer.parseInt(ageStr); if (age < 13 || age > 120) { throw new IllegalArgumentException("Age must be between 13 and 120"); } System.out.println("✅ Registration successful! Welcome, " + username); } catch (IllegalArgumentException e) { System.out.println("❌ Validation error: " + e.getMessage()); } catch (NumberFormatException e) { System.out.println("❌ Age error: Please enter a valid number for age"); } catch (Exception e) { System.out.println("❌ Unexpected error during registration: " + e.getMessage()); } } private static void validateEmail(String email) { if (email == null || !email.contains("@")) { throw new IllegalArgumentException("Invalid email format"); } // Simple email validation String emailRegex = "^[A-Za-z0-9+_.-]+@(.+)$"; if (!Pattern.matches(emailRegex, email)) { throw new IllegalArgumentException("Email format is invalid"); } } // Scenario 2: Network operations public static void checkWebsiteAvailability(String urlString) { System.out.println("\n=== WEBSITE AVAILABILITY CHECK ==="); System.out.println("Checking: " + urlString); try { URL url = new URL(urlString); // Simulate network check (in real app, you'd use HttpURLConnection) if (urlString.contains("example.com")) { System.out.println("✅ Website is available and responding"); } else if (urlString.contains("unavailable")) { throw new RuntimeException("Connection timeout - website not responding"); } else { throw new RuntimeException("HTTP 404 - Website not found"); } } catch (MalformedURLException e) { System.out.println("❌ URL error: Invalid URL format"); System.out.println("Please check the website address"); } catch (RuntimeException e) { System.out.println("❌ Network error: " + e.getMessage()); } catch (Exception e) { System.out.println("❌ Unexpected network error: " + e.getMessage()); } } // Scenario 3: Database operations public static void processDatabaseTransaction(String operation, String data) { System.out.println("\n=== DATABASE TRANSACTION ==="); System.out.println("Operation: " + operation); System.out.println("Data: " + data); try { // Simulate database connection if (!connectToDatabase()) { throw new RuntimeException("Cannot connect to database server"); } // Simulate different database operations switch (operation.toUpperCase()) { case "INSERT": if (data == null || data.isEmpty()) { throw new IllegalArgumentException("Insert data cannot be empty"); } System.out.println("✅ Data inserted successfully"); break; case "UPDATE": if (data.contains("invalid")) { throw new RuntimeException("Update failed - invalid data format"); } System.out.println("✅ Data updated successfully"); break; case "DELETE": if (data.equals("protected")) { throw new SecurityException("Cannot delete protected record"); } System.out.println("✅ Data deleted successfully"); break; default: throw new IllegalArgumentException("Unknown operation: " + operation); } // Commit transaction commitTransaction(); } catch (SecurityException e) { System.out.println("❌ Security violation: " + e.getMessage()); rollbackTransaction(); } catch (IllegalArgumentException e) { System.out.println("❌ Input error: " + e.getMessage()); rollbackTransaction(); } catch (RuntimeException e) { System.out.println("❌ Database error: " + e.getMessage()); rollbackTransaction(); } catch (Exception e) { System.out.println("❌ Unexpected database error: " + e.getMessage()); rollbackTransaction(); } finally { closeDatabaseConnection(); } } private static boolean connectToDatabase() { System.out.println("🔗 Connecting to database..."); return true; // Simulate successful connection } private static void commitTransaction() { System.out.println("💾 Committing transaction..."); } private static void rollbackTransaction() { System.out.println("↩️ Rolling back transaction..."); } private static void closeDatabaseConnection() { System.out.println("🔒 Closing database connection..."); } // Scenario 4: File processing with detailed error handling public static void processDataFile(String filename) { System.out.println("\n=== DATA FILE PROCESSING ==="); System.out.println("Processing file: " + filename); try { if (filename == null) { throw new IllegalArgumentException("Filename cannot be null"); } if (!filename.endsWith(".csv") && !filename.endsWith(".txt")) { throw new IllegalArgumentException("Only CSV and TXT files are supported"); } // Simulate file processing String[] lines = simulateFileReading(filename); int processedCount = 0; for (int i = 0; i < lines.length; i++) { try { processDataLine(lines[i], i + 1); processedCount++; } catch (DataProcessingException e) { System.out.println("⚠️ Skipping line " + (i + 1) + ": " + e.getMessage()); // Continue processing other lines } } System.out.println("✅ File processing completed"); System.out.println("Successfully processed: " + processedCount + " lines"); System.out.println("Failed: " + (lines.length - processedCount) + " lines"); } catch (IllegalArgumentException e) { System.out.println("❌ Configuration error: " + e.getMessage()); } catch (SecurityException e) { System.out.println("❌ Access denied: " + e.getMessage()); } catch (Exception e) { System.out.println("❌ File processing failed: " + e.getMessage()); } } private static String[] simulateFileReading(String filename) { if (filename.contains("corrupt")) { throw new RuntimeException("File is corrupt or unreadable"); } if (filename.contains("large")) { throw new RuntimeException("File too large to process"); } return new String[]{"valid data", "invalid format", "valid data", "missing fields"}; } private static void processDataLine(String line, int lineNumber) throws DataProcessingException { if (line.contains("invalid") || line.contains("missing")) { throw new DataProcessingException("Invalid data format in line " + lineNumber); } System.out.println("✅ Processed line " + lineNumber + ": " + line); } // Custom exception for business logic static class DataProcessingException extends Exception { public DataProcessingException(String message) { super(message); } } // Scenario 5: Retry mechanism with exception handling public static void executeWithRetry(Runnable operation, int maxRetries) { System.out.println("\n=== OPERATION WITH RETRY MECHANISM ==="); System.out.println("Max retries: " + maxRetries); int attempt = 1; while (attempt <= maxRetries) { try { System.out.println("Attempt " + attempt + "..."); operation.run(); System.out.println("✅ Operation completed successfully on attempt " + attempt); return; // Success - exit method } catch (RuntimeException e) { System.out.println("❌ Attempt " + attempt + " failed: " + e.getMessage()); if (attempt == maxRetries) { System.out.println("💥 All retry attempts exhausted. Operation failed."); throw e; // Re-throw after final attempt } // Wait before retry (exponential backoff) try { long waitTime = Math.min(1000 * (long) Math.pow(2, attempt - 1), 10000); System.out.println("⏳ Waiting " + waitTime + "ms before retry..."); Thread.sleep(waitTime); } catch (InterruptedException ie) { Thread.currentThread().interrupt(); throw new RuntimeException("Operation interrupted", ie); } attempt++; } } } public static void main(String[] args) { System.out.println("=== REAL-WORLD EXCEPTION HANDLING SCENARIOS ==="); // Scenario 1: User registration validateUserRegistration("john_doe", "[email protected]", "25"); validateUserRegistration("jo", "invalid-email", "not-a-number"); validateUserRegistration("", "[email protected]", "150"); // Scenario 2: Network operations checkWebsiteAvailability("https://example.com"); checkWebsiteAvailability("invalid-url"); checkWebsiteAvailability("https://unavailable-site.com"); // Scenario 3: Database operations processDatabaseTransaction("INSERT", "user data"); processDatabaseTransaction("UPDATE", "invalid data"); processDatabaseTransaction("DELETE", "protected"); processDatabaseTransaction("UNKNOWN", "data"); // Scenario 4: File processing processDataFile("data.csv"); processDataFile("corrupt.csv"); processDataFile("huge_data.csv"); // Scenario 5: Retry mechanism executeWithRetry(() -> { // Simulate flaky operation if (Math.random() < 0.7) { throw new RuntimeException("Temporary network failure"); } System.out.println("📡 Network operation successful!"); }, 3); System.out.println("\n=== ALL SCENARIOS COMPLETED ==="); } } Output:
=== REAL-WORLD EXCEPTION HANDLING SCENARIOS === === USER REGISTRATION VALIDATION === Username: john_doe Email: [email protected] Age: 25 ✅ Registration successful! Welcome, john_doe === USER REGISTRATION VALIDATION === Username: jo Email: invalid-email Age: not-a-number ❌ Validation error: Username must be at least 3 characters === USER REGISTRATION VALIDATION === Username: Email: [email protected] Age: 150 ❌ Validation error: Username cannot be empty === WEBSITE AVAILABILITY CHECK === Checking: https://example.com ✅ Website is available and responding === WEBSITE AVAILABILITY CHECK === Checking: invalid-url ❌ URL error: Invalid URL format Please check the website address === WEBSITE AVAILABILITY CHECK === Checking: https://unavailable-site.com ❌ Network error: Connection timeout - website not responding === DATABASE TRANSACTION === Operation: INSERT Data: user data 🔗 Connecting to database... ✅ Data inserted successfully 💾 Committing transaction... 🔒 Closing database connection... === DATABASE TRANSACTION === Operation: UPDATE Data: invalid data 🔗 Connecting to database... ❌ Database error: Update failed - invalid data format ↩️ Rolling back transaction... 🔒 Closing database connection... === DATABASE TRANSACTION === Operation: DELETE Data: protected 🔗 Connecting to database... ❌ Security violation: Cannot delete protected record ↩️ Rolling back transaction... 🔒 Closing database connection... === DATABASE TRANSACTION === Operation: UNKNOWN Data: data 🔗 Connecting to database... ❌ Input error: Unknown operation: UNKNOWN ↩️ Rolling back transaction... 🔒 Closing database connection... === DATA FILE PROCESSING === Processing file: data.csv ✅ Processed line 1: valid data ⚠️ Skipping line 2: Invalid data format in line 2 ✅ Processed line 3: valid data ⚠️ Skipping line 4: Invalid data format in line 4 ✅ File processing completed Successfully processed: 2 lines Failed: 2 lines === DATA FILE PROCESSING === Processing file: corrupt.csv ❌ File processing failed: File is corrupt or unreadable === DATA FILE PROCESSING === Processing file: huge_data.csv ❌ File processing failed: File too large to process === OPERATION WITH RETRY MECHANISM === Max retries: 3 Attempt 1... ❌ Attempt 1 failed: Temporary network failure ⏳ Waiting 1000ms before retry... Attempt 2... ❌ Attempt 2 failed: Temporary network failure ⏳ Waiting 2000ms before retry... Attempt 3... 📡 Network operation successful! ✅ Operation completed successfully on attempt 3 === ALL SCENARIOS COMPLETED ===
Example 5: Best Practices and Common Patterns
```java
import java.util.logging.*;
public class BestPractices {
private static final Logger logger = Logger.getLogger(BestPractices.class.getName());
// ✅ BEST PRACTICE 1: Use specific exceptions public static void specificVsGeneral() { System.out.println("=== SPECIFIC VS GENERAL EXCEPTIONS ==="); // ❌ BAD: Too general try { int[] arr = {1, 2, 3}; System.out.println(arr[5]); } catch (Exception e) { // ❌ Catches everything System.out.println("❌ Error occurred"); } // ✅ GOOD: Specific exceptions try { int[] arr = {1, 2, 3}; System.out.println(arr[5]); } catch (ArrayIndexOutOfBoundsException e) { System.out.println("✅ Specific: Array index out of bounds"); } catch (NullPointerException e) { System.out.println("✅ Specific: Null pointer exception"); } } // ✅ BEST PRACTICE 2: Don't ignore exceptions public static void dontIgnoreExceptions() { System.out.println("\n=== DON'T IGNORE EXCEPTIONS ==="); // ❌ BAD: Ignoring exception (empty catch block) try { int result = 10 / 0; } catch (ArithmeticException e) { // ❌ Empty - exception completely ignored! } // ✅ GOOD: Handle or log the exception try { int result = 10 / 0; } catch (ArithmeticException e) { System.out.println("✅ Handled: " + e.getMessage()); logger.warning("Division by zero attempted: " + e.getMessage()); } } // ✅ BEST PRACTICE 3: Use try-with-resources public static void useTryWithResources() { System.out.println("\n=== USE TRY-WITH-RESOURCES ==="); // ❌ BAD: Manual resource management /* FileInputStream fis = null; try { fis = new FileInputStream("file.txt"); // use stream } catch (IOException e) { // handle } finally { if (fis != null) { try { fis.close(); } catch (IOException e) { // ignore } } } */ // ✅ GOOD: Try-with-resources /* try (FileInputStream fis = new FileInputStream("file.txt"); BufferedReader reader = new BufferedReader(new InputStreamReader(fis))) { // use resources } catch (IOException e) { // handle exception } // Resources automatically closed */ System.out.println("✅ Use try-with-resources for automatic cleanup"); } // ✅ BEST PRACTICE 4: Provide useful error messages public static void usefulErrorMessages() { System.out.println("\n=== USEFUL ERROR MESSAGES ==="); // ❌ BAD: Vague error message try { String data = null; data.length(); } catch (Exception e) { System.out.println("❌ Error occurred"); // Not helpful } // ✅ GOOD: Descriptive error message try { String data = null; data.length(); } catch (NullPointerException e) { System.out.println("✅ Error: Attempted to call method on null object"); System.out.println(" Context: While processing user data"); System.out.println(" Action: Please check if data is properly initialized"); } } // ✅ BEST PRACTICE 5: Use custom exceptions for business logic public static void useCustomExceptions() { System.out.println("\n=== CUSTOM EXCEPTIONS ==="); try { processOrder(-1); // Invalid order ID } catch (InvalidOrderException e) { System.out.println("✅ Custom exception caught: " + e.getMessage()); System.out.println(" Error code: " + e.getErrorCode()); } try { processOrder(1000); // Non-existent order } catch (InvalidOrderException e) { System.out.println("✅ Custom exception caught: " + e.getMessage()); System.out.println(" Error code: " + e.getErrorCode()); } } private static void processOrder(int orderId) throws InvalidOrderException { if (orderId <= 0) { throw new InvalidOrderException("Order ID must be positive", "ERR_001"); } if (orderId > 100) { throw new InvalidOrderException("Order not found", "ERR_002"); } System.out.println("✅ Processing order: " + orderId); } // Custom exception class static class InvalidOrderException extends Exception { private final String errorCode; public InvalidOrderException(String message, String errorCode) { super(message); this.errorCode = errorCode; } public String getErrorCode() { return errorCode; } } // ✅ BEST PRACTICE 6: Exception translation public static void exceptionTranslation() { System.out.println("\n=== EXCEPTION TRANSLATION ==="); try { readConfigurationFile(); } catch (ConfigurationException e) { System.out.println("✅ Translated exception: " + e.getMessage()); System.out.println(" Original cause: " + e.getCause().getMessage()); } } private static void readConfigurationFile() throws ConfigurationException { try { // Simulate low-level IO operation throw new java.io.FileNotFoundException("config.properties not found"); } catch (java.io.IOException e) { // Translate to business-level exception throw new ConfigurationException("Failed to read configuration", e); } } static class ConfigurationException extends Exception { public ConfigurationException(String message, Throwable cause) { super(message, cause); } } // ✅ BEST PRACTICE 7: Use finally for cleanup, not business logic public static void properFinallyUsage() { System.out.println("\n=== PROPER FINALLY USAGE ==="); // ❌ BAD: Business logic in finally /* try { // some operation } finally { if (success) { // ❌ Don't put conditions in finally commitTransaction(); } } */ // ✅ GOOD: Cleanup only in finally boolean success = false; try { System.out.println("Performing operation..."); success = true; // Operation successful