Menu

Java try-catch: Handle Exceptions Without Crashing

How to use Java's try-catch to handle exceptions - catching specific types, the finally block, try-with-resources, and the mistakes that hide bugs.

This page includes runnable editors - edit, run, and see output instantly.

Catching an Exception Instead of Crashing

You already know that when something goes wrong, Java throws an exception, and an unhandled exception stops your program with a stack trace. A try-catch block is how you take control: you wrap the risky code in try, and if it throws, Java jumps to the matching catch block instead of crashing.

The moment 10 / 0 throws, the rest of the try block is skipped and control moves to catch. After the catch finishes, execution continues normally - the program does not die.

The catch Variable Holds the Exception

The e in catch (ArithmeticException e) is a real object. It carries information about what went wrong, most usefully a message:

e.getMessage() returns a short description. During debugging, e.printStackTrace() dumps the full trace showing exactly where the exception came from - reach for that when a message alone is not enough to find the cause.

Catch the Specific Type, Not Everything

A catch block only catches exceptions that match its declared type (or a subclass). The biggest beginner mistake is catching Exception to make a problem "go away":

// Don't do this - it hides real bugs
try {
    doWork();
} catch (Exception e) {
    // swallows NullPointerException, typos, logic errors... everything
}

Catch the narrowest type you can genuinely handle. If you expect bad number input, catch NumberFormatException. Anything you did not anticipate should be allowed to propagate so you actually find out about it instead of silently continuing in a broken state.

Handling Several Exception Types

You can stack multiple catch blocks. Java checks them top to bottom and runs the first one that matches, so order from most specific to most general:

When two types share the same handling, use a single multi-catch with | instead of duplicating the block:

A gotcha: a more general type must come after the specific ones. Putting catch (Exception e) first makes the later, more specific blocks unreachable, and the compiler rejects it.

finally Always Runs

A finally block runs after the try and any catch, regardless of what happened - success, a caught exception, or even an early return. It is where cleanup that must always happen belongs.

"Closing resource" prints whether or not the exception fires. Avoid returning from inside finally, though - it can quietly discard an exception or override a value returned from the try block.

try-with-resources Closes Things for You

When you work with something that must be closed - a file, a network connection, a database statement - declaring it inside try (...) closes it automatically when the block ends, even if an exception is thrown. Any type that implements the AutoCloseable interface works.

This replaces the old pattern of opening in try and closing in finally, and it is less error-prone because you cannot forget the close. Prefer it whenever you are dealing with a closeable resource.

Don't Use Exceptions for Normal Control Flow

try-catch is for exceptional situations, not ordinary conditions. Catching an exception is more expensive than a plain check, and it makes code harder to read. If you can test the condition first with an if-else check, do that instead:

// Avoid: using a catch to test for a missing key
try {
    process(map.get(key).trim());
} catch (NullPointerException e) {
    // handle missing key
}

// Prefer: check explicitly
String value = map.get(key);
if (value != null) {
    process(value.trim());
}

Reserve catch for things genuinely outside your control - bad user input, missing files, network failures.

Next: NullPointerException

The single most common exception you will catch (and cause) in Java is the NullPointerException - it shows up the instant you call a method on something that turned out to be null. Next we will dig into exactly what triggers it, how to read its stack trace, and the habits that keep it from happening in the first place.

Frequently Asked Questions

How do you use try-catch in Java?

Put the code that might throw inside a try block, then add a catch block naming the exception type you want to handle: try { risky(); } catch (IOException e) { ... }. If the try code throws a matching exception, Java jumps straight to the catch block instead of crashing. The variable (e) holds the exception object so you can read its message with e.getMessage().

What is the finally block for in Java?

A finally block runs after try/catch no matter what - whether the code succeeded, threw, or even returned early. It is the place for cleanup that must always happen, like closing a file or releasing a lock. For closing resources, try-with-resources is usually cleaner because it closes them automatically.

Should you catch Exception or a specific exception type?

Catch the most specific type you can actually handle. Catching Exception (or worse, Throwable) swallows every problem - including bugs like NullPointerException - and hides the real cause. Catch NumberFormatException if that is what you expect, and let unexpected exceptions propagate so you find out about them.

Coddy programming languages illustration

Learn to code with Coddy

GET STARTED