Syntax
try {\n // risky code\n} catch (ExceptionType e) {\n // handle it\n} finally {\n // always runs\n}Breaking down the syntax
try- Groups operations whose failures you want to handle.
catch- Handles a matching exception.
throw- Raises an exception now.
throws IOException- Declares that a method can pass a checked I/O exception to its caller.
How it works
An exception interrupts normal execution. Catch a specific failure when your program can respond, or let a caller handle it.
Start with a small example
Run the first example, then change one value and predict the result.
Apply the idea
Compare the alternatives below before using this pattern in your own project.
Examples
Recover from invalid input
Save as Main.java; compile with javac Main.java and run java Main.
public class Main {
public static void main(String[] args) {
try {
int lessons = Integer.parseInt("three");
System.out.println(lessons);
} catch (NumberFormatException error) {
System.out.println("Please enter a whole number.");
}
System.out.println("Ready to try again.");
}
}- Save as Main.java; compile with javac Main.java and run java Main.
- The conversion fails before the first println, then execution continues after the catch.
Validate a method argument
Rejects an invalid value before calculating.
public class Main {
static int remaining(int completed) {
if (completed < 0 || completed > 10) {
throw new IllegalArgumentException("Completed must be between 0 and 10.");
}
return 10 - completed;
}
public static void main(String[] args) {
try {
System.out.println(remaining(12));
} catch (IllegalArgumentException error) {
System.out.println(error.getMessage());
}
}
}- Rejects an invalid value before calculating.
- The caller displays the exception message. Save as Main.java.
Basic try / catch
Catching an exception instead of letting the program crash.
try {
int result = 10 / 0;
} catch (ArithmeticException e) {
System.out.println("Error: " + e.getMessage());
}
System.out.println("Program continues running");Catching Multiple Exception Types
Handling different exceptions differently with multiple catch blocks.
public static void process(String input) {
try {
int number = Integer.parseInt(input);
int result = 100 / number;
System.out.println(result);
} catch (NumberFormatException e) {
System.out.println("Not a valid number: " + input);
} catch (ArithmeticException e) {
System.out.println("Cannot divide by zero");
}
}
process("abc"); // Not a valid number: abc
process("0"); // Cannot divide by zero
process("5"); // 20finally Block
Code in finally always executes, whether or not an exception was thrown - ideal for cleanup.
public static void readFile() {
System.out.println("Opening file...");
try {
throw new RuntimeException("File not found");
} catch (RuntimeException e) {
System.out.println("Error: " + e.getMessage());
} finally {
System.out.println("Closing file..."); // always runs
}
}
readFile();Custom Exceptions
Defining and throwing your own exception type for domain-specific error handling.
class InsufficientFundsException extends Exception {
public InsufficientFundsException(String message) {
super(message);
}
}
class BankAccount {
private double balance;
public BankAccount(double balance) { this.balance = balance; }
public void withdraw(double amount) throws InsufficientFundsException {
if (amount > balance) {
throw new InsufficientFundsException("Not enough funds for this withdrawal");
}
balance -= amount;
}
}
BankAccount account = new BankAccount(100);
try {
account.withdraw(200);
} catch (InsufficientFundsException e) {
System.out.println("Transaction failed: " + e.getMessage());
}Best practices
- Catch specific exception types rather than a broad catch (Exception e), so unrelated bugs are not accidentally silenced
- Use finally (or try-with-resources) for cleanup code that absolutely must run, like closing files or database connections
- Create custom exception classes for domain-specific errors, extending Exception (checked) or RuntimeException (unchecked) depending on whether callers should be forced to handle them
- Don't use exceptions for routine control flow when a simple if check would do - they carry real performance overhead and should signal genuinely exceptional situations
Runtime & versions
Java Virtual Machine. Feature availability depends on the language and runtime version used by your project; consult the official reference below.
Java Language SpecificationWhen should I use this?
Recover from invalid input. Distinguish throw from throws. Choose specific handlers.
Common mistakes
Hiding a failure
An empty handler hides that the operation failed.
Incorrect
catch (NumberFormatException error) {}Corrected
catch (NumberFormatException error) {
System.out.println("Please enter a whole number.");
}Compare approaches
- Checked exceptions: Catch or declare failures such as IOException.
- Unchecked exceptions: RuntimeException subclasses do not require a throws declaration.
- Try-with-resources: Close readers and similar resources automatically.
Explore deeper
Cleanup and ordering
Prefer try-with-resources for AutoCloseable objects. finally cannot guarantee execution if the JVM terminates. Put specific handlers before their supertypes.