DEV Community

Abishek
Abishek

Posted on

Exception Handling

What is an Exception?

The Oracle docs define it cleanly —

"An exception is an event, which occurs during the execution of a program, that disrupts the normal flow of the program's instructions."
Oracle Java Tutorials

When an error happens inside a method, the method creates an exception object — which holds information about the error: its type and the state of the program when it occurred. That object is handed off to the runtime system. This is called throwing an exception.

The runtime then searches back through the call stack — the ordered list of methods that were called — looking for something that can handle it. If it finds nothing, the program terminates.


The Hierarchy — Error vs Exception

Not everything that goes wrong is the same. Java separates them clearly:

Throwable
├── Error             ← JVM level. You can't fix this. (OutOfMemoryError, StackOverflowError)
└── Exception         ← You CAN handle this
    ├── Checked       ← Compiler forces you to handle (IOException, SQLException)
    └── Unchecked     ← Runtime surprises (NullPointerException, ArrayIndexOutOfBoundsException)
Enter fullscreen mode Exit fullscreen mode

The Error class exists separately from Exception for a reason — it allows programs to use catch (Exception e) to catch recoverable problems without accidentally catching errors from which recovery is typically not possible.

Simple rule:

  • Error — JVM is in trouble. Don't catch it. Fix the root cause.
  • Checked Exception — Compiler screams at you. You must handle it.
  • Unchecked Exception — Runtime surprise. Fix your logic.

The Keywords — one by one

try

Wrap the risky code here. Code that might throw an exception.

try {
    int result = 10 / 0; // risky!
}
Enter fullscreen mode Exit fullscreen mode

catch

If something goes wrong in try, catch it here. Program doesn't crash.

According to Oracle, exception handlers can do more than just print error messages — they can do error recovery, prompt the user to make a decision, or propagate the error up to a higher-level handler.

try {
    int result = 10 / 0;
} catch (ArithmeticException e) {
    System.out.println("Can't divide by zero: " + e.getMessage());
}
Enter fullscreen mode Exit fullscreen mode

Java 7+ bonus — one catch block can handle multiple exceptions:

catch (IOException | SQLException e) {
    logger.log(e);
    throw e;
}
Enter fullscreen mode Exit fullscreen mode

Cleaner code, less repetition.

finally

Runs always — whether exception happened or not. This is where you do cleanup — close DB connections, close files, release resources.

try {
    int result = 10 / 0;
} catch (ArithmeticException e) {
    System.out.println("Error caught");
} finally {
    System.out.println("This always runs — cleanup here");
}
Enter fullscreen mode Exit fullscreen mode

throw

Manually trigger an exception yourself.

if (age < 0) {
    throw new IllegalArgumentException("Age can't be negative");
}
Enter fullscreen mode Exit fullscreen mode

throws

Used in method signature — a warning that this method might throw an exception. The caller must handle it.

As Oracle explains — if a method doesn't catch the checked exceptions that can occur within it, the method must specify that it can throw those exceptions using throws.

public void readFile(String path) throws IOException {
    // risky file reading code
}
Enter fullscreen mode Exit fullscreen mode

throw vs throws in one line:

  • throw — you're throwing the ball right now
  • throws — you're warning someone a ball might come

What to actually DO with errors

Three honest options:

1. Handle it and continue

} catch (NumberFormatException e) {
    System.out.println("Enter a valid number");
    // ask user to re-enter, continue program
}
Enter fullscreen mode Exit fullscreen mode

2. Log it and rethrow (TBD)

} catch (IOException e) {
    logger.error("File read failed", e);
    throw e; // let the caller deal with it
}
Enter fullscreen mode Exit fullscreen mode

3. Wrap and throw a custom exception

} catch (SQLException e) {
    throw new DatabaseException("DB connection failed", e);
}
Enter fullscreen mode Exit fullscreen mode

Key Points

  • Always catch specific exceptions first, then general ones
  • A specific handler targets one exact error; a general handler using a superclass like IOException catches all its subclasses too
  • finally is for cleanup — DB connections, file streams, resources
  • Never catch Error — those are JVM-level failures, not yours to fix
  • Checked exceptions — compiler forces you to handle them
  • Unchecked exceptions — runtime issues, fix your code logic
try {
    // risky code
} catch (FileNotFoundException e) { // specific first
    System.out.println("File not found: " + e.getMessage());
} catch (IOException e) {           // general after
    System.out.println("IO error: " + e.getMessage());
} finally {
    // close connection, file, etc.
}
Enter fullscreen mode Exit fullscreen mode

Exceptions vs Errors — final summary

Exception Error
Recoverable? ✅ Yes ❌ No
Should you catch? ✅ Yes ❌ Avoid
Example IOException, NullPointerException OutOfMemoryError, StackOverflowError
Cause Bad logic / external issues JVM failure

References: Oracle Java Exception TutorialJava Language Spec — Exceptions

Top comments (0)