foreach-ui logo
codeLanguages
account_treeDSA

Quick Actions

quizlock Random Quiz
trending_uplock Progress
  • 1
  • 2
  • 3
  • 4
  • quiz
Java
  • Master the syntax and usage of try-catch blocks
  • Learn how to catch multiple exception types
  • Understand the finally block and its use cases
  • Learn how to throw custom exceptions
  • Understand exception propagation and the throws keyword

Try-Catch Blocks and Exception Types

You know what exceptions are. Now you need to catch them before they crash your program.

The Try-Catch Block: Your Safety Net

The try-catch block is Java's fundamental mechanism for handling exceptions. Think of it as a safety net that catches errors before they bring everything down.

Basic Syntax

try {
    // Code that might throw an exception
    int result = 10 / 0;
} catch (ArithmeticException e) {
    // Code to handle the exception
    System.out.println("Error: Cannot divide by zero!");
}
System.out.println("Program continues normally...");

How it works:

  1. Java tries to execute code in the try block
  2. If an exception occurs, execution immediately jumps to the matching catch block
  3. The catch block handles the error
  4. Program continues after the try-catch

Real Example: User Input Validation

Scanner scanner = new Scanner(System.in);
System.out.print("Enter a number: ");

try {
    int number = scanner.nextInt();
    System.out.println("You entered: " + number);
    int result = 100 / number;
    System.out.println("100 divided by " + number + " = " + result);
} catch (InputMismatchException e) {
    System.out.println("Error: Please enter a valid integer!");
} catch (ArithmeticException e) {
    System.out.println("Error: Cannot divide by zero!");
}
System.out.println("Thank you for using the calculator!");

Output Examples:

Valid input (5):

Enter a number: 5
You entered: 5
100 divided by 5 = 20
Thank you for using the calculator!

Invalid input (abc):

Enter a number: abc
Error: Please enter a valid integer!
Thank you for using the calculator!

Zero input:

Enter a number: 0
You entered: 0
Error: Cannot divide by zero!
Thank you for using the calculator!

Notice the program doesn't crash - it handles errors gracefully!

Multiple Catch Blocks

You can catch different exception types and handle them differently:

public void readAndParseFile(String filename) {
    try {
        File file = new File(filename);
        Scanner scanner = new Scanner(file);
        
        while (scanner.hasNextLine()) {
            String line = scanner.nextLine();
            int value = Integer.parseInt(line);
            System.out.println("Parsed: " + value);
        }
        
        scanner.close();
        
    } catch (FileNotFoundException e) {
        System.out.println("Error: File '" + filename + "' not found.");
        System.out.println("Please check the filename and try again.");
        
    } catch (NumberFormatException e) {
        System.out.println("Error: File contains non-numeric data.");
        System.out.println("Line: " + e.getMessage());
        
    } catch (Exception e) {
        System.out.println("An unexpected error occurred: " + e.getMessage());
        e.printStackTrace();
    }
}

Order matters! Always catch specific exceptions before general ones:

// GOOD - Specific to general
try {
    riskyCode();
} catch (FileNotFoundException e) {      // Most specific
    // Handle file not found
} catch (IOException e) {                // More general
    // Handle other I/O errors
} catch (Exception e) {                  // Most general
    // Handle any other exception
}

// BAD - Won't compile!
try {
    riskyCode();
} catch (Exception e) {        // Too general, catches everything
    // Handle exception
} catch (IOException e) {      // Never reached! Compilation error!
    // This code is unreachable
}

Multi-Catch: Handling Multiple Exceptions the Same Way

Java 7+ lets you catch multiple exception types in one catch block:

try {
    String data = readFromNetwork();
    int value = Integer.parseInt(data);
    saveToDatabase(value);
    
} catch (IOException | NumberFormatException e) {
    // Handle both exceptions the same way
    System.out.println("Error processing data: " + e.getMessage());
    logError(e);
}

Benefits:

  • Less code duplication
  • Cleaner and more readable
  • Same handling for related exceptions

Rules:

  • Exception types separated by pipe |
  • Can't catch exception and its subclass together
  • The exception variable is implicitly final

The Finally Block: Always Execute

The finally block always executes, whether an exception occurs or not. It's perfect for cleanup operations.

BufferedReader reader = null;
try {
    reader = new BufferedReader(new FileReader("data.txt"));
    String line = reader.readLine();
    System.out.println(line);
    
} catch (IOException e) {
    System.out.println("Error reading file: " + e.getMessage());
    
} finally {
    // This ALWAYS runs!
    if (reader != null) {
        try {
            reader.close();
            System.out.println("File closed successfully");
        } catch (IOException e) {
            System.out.println("Error closing file");
        }
    }
}

When does finally execute?

  • ✅ When no exception occurs
  • ✅ When exception is caught
  • ✅ When exception is not caught (before propagating)
  • ✅ Even if there's a return statement in try or catch
  • ❌ Only if JVM exits (System.exit()) or thread dies

Finally with Return Statements

public int demonstrateFinally() {
    try {
        return 1;  // Would return here...
    } finally {
        System.out.println("Finally executes even with return!");
        // Finally runs before method actually returns!
    }
}

Output:

Finally executes even with return!

Then returns 1.

Try-With-Resources: Automatic Cleanup (Java 7+)

A modern, cleaner way to handle resources that need closing:

// Old way - verbose
BufferedReader reader = null;
try {
    reader = new BufferedReader(new FileReader("file.txt"));
    String line = reader.readLine();
    System.out.println(line);
} catch (IOException e) {
    e.printStackTrace();
} finally {
    if (reader != null) {
        try {
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

// New way - clean and automatic!
try (BufferedReader reader = new BufferedReader(new FileReader("file.txt"))) {
    String line = reader.readLine();
    System.out.println(line);
} catch (IOException e) {
    e.printStackTrace();
}
// reader.close() is called automatically!

Benefits:

  • Resources automatically closed
  • Less boilerplate code
  • Prevents resource leaks
  • Multiple resources supported
// Multiple resources
try (FileReader fr = new FileReader("input.txt");
     BufferedReader br = new BufferedReader(fr);
     FileWriter fw = new FileWriter("output.txt")) {
    
    String line;
    while ((line = br.readLine()) != null) {
        fw.write(line + "\n");
    }
    // All three resources closed automatically!
}

Throwing Exceptions

Sometimes you need to throw exceptions yourself:

Using 'throw'

public void setAge(int age) {
    if (age < 0 || age > 150) {
        throw new IllegalArgumentException(
            "Age must be between 0 and 150, got: " + age
        );
    }
    this.age = age;
}

Custom Exception Messages

public void withdraw(double amount) {
    if (amount > balance) {
        throw new IllegalStateException(
            "Insufficient funds. Balance: $" + balance + 
            ", Requested: $" + amount
        );
    }
    balance -= amount;
}

The 'throws' Keyword: Declaring Exceptions

When you don't want to handle an exception in a method, declare it with throws:

// This method declares it might throw IOException
public String readFile(String filename) throws IOException {
    BufferedReader reader = new BufferedReader(new FileReader(filename));
    String content = reader.readLine();
    reader.close();
    return content;
}

// Caller must handle it
public void processFile() {
    try {
        String data = readFile("data.txt");
        System.out.println(data);
    } catch (IOException e) {
        System.out.println("Error: " + e.getMessage());
    }
}

Multiple exceptions:

public void complexOperation() throws IOException, SQLException {
    // Method that might throw both exceptions
}

Difference: throw vs throws

  • throw - Actually throws an exception (used in method body)
  • throws - Declares that a method might throw exceptions (in signature)
public void example() throws IOException {  // throws - declares
    if (someCondition) {
        throw new IOException("Error!");    // throw - actually throws
    }
}

Exception Propagation

When an exception isn't caught, it propagates up the call stack:

public void method1() {
    method2();
}

public void method2() {
    method3();
}

public void method3() {
    throw new RuntimeException("Error in method3!");
}

// Call chain: method1() → method2() → method3() → Exception!
// Exception propagates: method3() → method2() → method1() → caller

Example with handling:

public void method1() {
    try {
        method2();
    } catch (RuntimeException e) {
        System.out.println("Caught in method1: " + e.getMessage());
    }
}

public void method2() {
    method3();  // Exception propagates from here
}

public void method3() {
    throw new RuntimeException("Error!");
}

Creating Custom Exceptions

For application-specific errors, create custom exception classes:

// Custom checked exception
public class InsufficientFundsException extends Exception {
    private double deficit;
    
    public InsufficientFundsException(double deficit) {
        super("Insufficient funds. Deficit: $" + deficit);
        this.deficit = deficit;
    }
    
    public double getDeficit() {
        return deficit;
    }
}

// Usage
public void withdraw(double amount) throws InsufficientFundsException {
    if (amount > balance) {
        double deficit = amount - balance;
        throw new InsufficientFundsException(deficit);
    }
    balance -= amount;
}

// Handling
try {
    account.withdraw(1000);
} catch (InsufficientFundsException e) {
    System.out.println(e.getMessage());
    System.out.println("You need $" + e.getDeficit() + " more.");
}

Best Practices

1. Catch Specific Exceptions

// GOOD
try {
    code();
} catch (FileNotFoundException e) {
    // Handle missing file
} catch (IOException e) {
    // Handle I/O errors
}

// BAD
try {
    code();
} catch (Exception e) {
    // Too broad!
}

2. Don't Catch What You Can't Handle

// BAD - catching but not handling
try {
    code();
} catch (IOException e) {
    // Empty - exception disappears!
}

// GOOD - at least log it
try {
    code();
} catch (IOException e) {
    logger.error("Failed to process file", e);
    throw e;  // Re-throw if can't handle
}

3. Provide Meaningful Messages

// BAD
throw new Exception("Error");

// GOOD
throw new FileNotFoundException(
    "Configuration file 'config.xml' not found in directory: " + dir
);

4. Clean Up Resources

// GOOD - Use try-with-resources
try (Connection conn = getConnection()) {
    // Use connection
}

// Or use finally
Connection conn = null;
try {
    conn = getConnection();
    // Use connection
} finally {
    if (conn != null) conn.close();
}

Key Takeaways

  • try-catch blocks handle exceptions and prevent crashes
  • Multiple catch blocks handle different exceptions differently
  • Multi-catch handles multiple exceptions the same way (Java 7+)
  • finally always executes - perfect for cleanup
  • try-with-resources automatically closes resources
  • throw creates and throws an exception
  • throws declares that a method might throw exceptions
  • Exceptions propagate up the call stack until caught
  • Custom exceptions provide application-specific error handling
  • Always close resources in finally or use try-with-resources

What's Next?

Now that you can handle exceptions like a pro, we'll explore a common source of exceptions: file input/output! In the next lesson, you'll learn:

  • How to read from and write to files
  • Different ways to handle file paths
  • Working with text and binary files
  • Best practices for file operations

Get ready to make your programs interact with the file system!

© 2026 forEach. All rights reserved.

Privacy Policy•Terms of Service