try, catch & finally
try, catch & finally
In the previous lesson you learned what exceptions are and why they exist. Now it is time to learn the three keywords that let you handle them: try, catch, and finally. Together they give you a structured way to wrap risky code, recover from problems, and guarantee cleanup — no matter what happens.
Why wrap code at all?
Without exception handling, any unexpected event — a file that does not exist, a network timeout, a bad user input — crashes your whole program. With a try block you draw a protective boundary around the risky code. If something goes wrong inside that boundary, Java looks for a matching catch block instead of halting.
The try block
A try block contains the statements that might throw an exception. It cannot stand alone — it must be followed by at least one catch block, a finally block, or both.
Here 10 / 0 throws an ArithmeticException. Because the statement is inside a try block, Java transfers control to the matching catch block instead of crashing the application.
The catch block
A catch block declares the type of exception it handles and gives it a local name (by convention e or ex). You can only catch exceptions that are either the exact type thrown or a parent type in the hierarchy (more on that in Lesson 3).
Notice that the line System.out.println("Parsed: " + number) never runs when parsing fails. Java jumps directly from the point of failure to the catch block, then continues after the entire try-catch construct.
e is an object. It carries information about what went wrong. The most useful methods are e.getMessage() (a short description) and e.toString() (type + message). For debugging during development, e.printStackTrace() prints the full call chain.
Multiple catch blocks
A single try block can be followed by several catch blocks, each handling a different exception type. Java checks them top-to-bottom and runs the first one that matches.
FileNotFoundException is a subclass of IOException. If you put the IOException catch block first it would swallow FileNotFoundException too, and the compiler would flag the second block as unreachable. Always order catch blocks from most specific to most general.
The finally block
The finally block runs no matter what — whether the try block succeeded, whether an exception was caught, or even if an exception was thrown and not caught. It is the right place for cleanup code: closing a connection, releasing a lock, flushing a buffer.
Even if new FileReader("config.txt") throws and the catch block runs, the finally block still executes afterward. This guarantee is what makes finally reliable for resource management.
AutoCloseable objects (covered in Lesson 8). For now, understanding the manual finally approach teaches you exactly what try-with-resources does automatically.
Control flow at a glance
- If no exception is thrown:
trybody runs fully,catchis skipped,finallyruns. - If a caught exception is thrown:
trystops at the throw point, the matchingcatchruns,finallyruns. - If an uncaught exception is thrown:
trystops, allcatchblocks are skipped,finallystill runs, then the exception propagates up the call stack.
finally block contains a return statement, it silently discards any exception that was in flight. This is one of the most confusing bugs in Java. Keep finally blocks focused on cleanup, not on returning values.
A complete worked example
Here is a small method that reads an integer from a string, combines all three blocks, and shows the control flow clearly:
Summary
Use try to mark code that might fail, catch to handle specific problems gracefully, and finally to guarantee cleanup regardless of outcome. Order multiple catch blocks from specific to general. In the next lesson you will explore the full exception hierarchy so you understand exactly which types to catch and when.