Java > Core Java > Exception Handling > Throw vs Throws

Throw vs Throws: Custom Exception Handling

This example demonstrates the difference between `throw` and `throws` in Java exception handling. `throw` is used to explicitly raise an exception within a method, while `throws` is used in the method signature to declare that the method might throw a specific exception (or its subclasses). This allows the calling method to handle the exception, promoting robust and predictable code.

Code Example

This code defines a custom exception `InsufficientFundsException`. The `BankAccount` class demonstrates how to use `throws` to declare that the `withdraw` method might throw this exception. Inside the `withdraw` method, `throw` is used to explicitly raise the `InsufficientFundsException` when the withdrawal amount exceeds the available balance. The `main` method demonstrates how to handle this exception using a `try-catch` block. The `finally` block ensures the current balance is always printed.

// Custom exception class
class InsufficientFundsException extends Exception {
    public InsufficientFundsException(String message) {
        super(message);
    }
}

// Class demonstrating throw and throws
class BankAccount {
    private double balance;

    public BankAccount(double initialBalance) {
        this.balance = initialBalance;
    }

    // Method that declares it might throw an exception using 'throws'
    public void withdraw(double amount) throws InsufficientFundsException {
        if (amount > balance) {
            // 'throw' is used to explicitly raise the exception
            throw new InsufficientFundsException("Insufficient funds. Available balance: " + balance);
        }
        balance -= amount;
        System.out.println("Withdrawal successful. New balance: " + balance);
    }

    public double getBalance() {
        return balance;
    }
}

// Main class to test the BankAccount class
public class ThrowVsThrows {
    public static void main(String[] args) {
        BankAccount account = new BankAccount(100.0);

        try {
            account.withdraw(150.0);
        } catch (InsufficientFundsException e) {
            System.err.println("Exception caught: " + e.getMessage());
        } finally {
            System.out.println("Current balance: " + account.getBalance());
        }

        try {
            account.withdraw(50.0);
        } catch (InsufficientFundsException e) {
            System.err.println("Exception caught: " + e.getMessage());
        } finally {
            System.out.println("Current balance: " + account.getBalance());
        }
    }
}

Concepts Behind the Snippet

`throw` and `throws` are fundamental keywords in Java's exception handling mechanism. `throw` is used to explicitly create and propagate an exception object. It's a statement within a method's body that signals an error or exceptional condition. `throws` is a clause in a method's declaration that specifies the exceptions that the method might throw. It's part of the method signature and acts as a contract with the caller, informing them of the potential exceptions they need to handle. Checked exceptions (exceptions that inherit from `Exception` but not `RuntimeException`) *must* be either caught in a `try-catch` block or declared in the method's `throws` clause. Unchecked exceptions (exceptions that inherit from `RuntimeException`) do not *need* to be declared, but it's good practice to document them.

Real-Life Use Case

Consider a banking application. When a user attempts to withdraw more money than is available in their account, an `InsufficientFundsException` should be thrown. The method responsible for processing the withdrawal would `throw` this exception if the balance is insufficient. The calling code, perhaps a transaction processing module, would `catch` this exception and handle it appropriately, such as displaying an error message to the user. The `throws` clause on the withdraw method ensures that any code calling withdraw is aware of the potential for this exception to occur and can handle it gracefully. Other use cases include handling file not found errors, network connection issues, or invalid data input.

Best Practices

  • Be specific with exception types: Throw and declare the most specific exception possible. This makes it easier for the calling code to handle the exception appropriately.
  • Document exceptions: Clearly document the exceptions that a method might throw in the Javadoc.
  • Avoid catching `Exception` or `Throwable` unless necessary: Catching broad exception types can mask specific exceptions and make debugging difficult.
  • Use `finally` blocks for resource cleanup: Ensure that resources (e.g., files, network connections) are always released, even if an exception occurs.
  • Throw exceptions early: Validate input and throw exceptions as soon as an invalid state is detected (fail-fast approach).

Interview Tip

A common interview question is to explain the difference between `throw` and `throws`. Be sure to explain that `throw` is a statement used to explicitly raise an exception, while `throws` is a clause in a method signature that declares the exceptions the method might throw. Also be prepared to discuss checked vs. unchecked exceptions, and the implications of each.

When to Use Them

  • Use throw when you detect an error condition within a method that you want to signal to the calling code. This is your way of saying, "Something went wrong; I can't continue.".
  • Use throws when a method might potentially throw a checked exception that it doesn't handle itself. This informs the calling code that it needs to either handle the exception (using try-catch) or declare that it might throw the exception as well (using throws). You do not need to use throws for unchecked exceptions (RuntimeExceptions), but it's often good practice for clarity.

Alternatives

Alternatives to throwing exceptions include:

  • Returning an error code: Instead of throwing an exception, a method could return a special value indicating an error (e.g., `null`, `-1`). However, this approach can be less clear and easier to ignore.
  • Using an `Optional` (Java 8+): For methods that might not return a value, an `Optional` can be used to represent the absence of a value, rather than throwing a `NullPointerException`.
Exceptions, however, are generally preferred for truly exceptional circumstances that prevent a method from fulfilling its contract.

Pros

  • Clear error signaling: Exceptions provide a clear and structured way to signal errors.
  • Centralized error handling: `try-catch` blocks allow for centralized error handling, making code more maintainable.
  • Unwinding the call stack: Exceptions automatically unwind the call stack until a suitable handler is found.
  • Forced error handling: Checked exceptions force the calling code to handle potential errors.

Cons

  • Performance overhead: Throwing and catching exceptions can be relatively expensive in terms of performance, especially if they are used frequently for non-exceptional conditions.
  • Code complexity: Exception handling can add complexity to code, especially with nested `try-catch` blocks.
  • Potential for abuse: Exceptions should be used for exceptional circumstances, not for normal control flow. Overuse of exceptions can make code harder to read and maintain.

FAQ

  • What is the difference between a checked and an unchecked exception?

    A checked exception is an exception that the compiler forces you to handle (either by catching it or declaring it in the `throws` clause). Checked exceptions inherit from `Exception` but not `RuntimeException`. An unchecked exception is an exception that the compiler does not force you to handle. Unchecked exceptions inherit from `RuntimeException`.
  • When should I use a custom exception?

    You should use a custom exception when you need to represent an error condition that is specific to your application or domain. This allows you to provide more meaningful error messages and handle the exception in a more targeted way.
  • Is it possible to re-throw an exception?

    Yes, you can re-throw an exception in a `catch` block using the `throw` keyword. This is useful when you need to perform some cleanup or logging before propagating the exception to a higher level.
  • What happens if an exception is not caught?

    If an exception is not caught, the program will terminate abruptly. The JVM will print a stack trace to the console, indicating the type of exception and the location where it occurred.