Skip to main content

Section 7.2 Standard Library Exceptions

Subsection 7.2.1 Preventing a Bill-Splitting Crash

Imagine you’re writing a program to split a restaurant bill among friends:
Running this code will throw an ArithmeticException, because dividing by zero is undefined. This runtime crash could surprise you (or your users).
So how can you prevent it?
  • Option 1 (Manual Check): Before dividing, do if (numberOfPeople == 0) { /* handle error */ }. This way, you ensure no crash occurs.
  • Option 2 (Exceptions): If you forget the check, Java automatically throws ArithmeticException. But it’s an unchecked exception, so the compiler doesn’t force you to handle it.
This raises a question: Why does Java sometimes force you to handle errors, and other times let them slip by until runtime? That’s exactly what we’ll explore now.

Subsection 7.2.2 Categories of Java Exceptions

In Java, when something goes wrong, the program can throw different types of exceptions. These fall into three main categories:
1. Errors
  • Category: Error
  • Purpose: Critical failures that affect the entire system. Not meant to be handled.
  • Examples: OutOfMemoryError, StackOverflowError
  • Do You Handle It? ❌ No, usually unfixable.
2. Checked Exceptions
  • Category: Checked Exception
  • Purpose: Recoverable failures that Java forces you to either handle (try/catch) or declare (throws).
  • Examples: IOException, ClassNotFoundException
  • Do You Handle It? ⚠️ Required: Either (try/catch) OR (throws).
3. Unchecked Exceptions
  • Category: Unchecked Exception
  • Purpose: Programmer mistakes that cause a crash at runtime.
  • Examples: ArithmeticException, NullPointerException
  • Do You Handle It? 🔶 You can handle them, but Java doesn’t force you to.
All of these categories belong to a broader group called Throwable. Java splits these into two main groups:
  • Errors like OutOfMemoryError indicate system-level failures. You almost never handle them directly—if your program runs out of memory, there’s often little you can do.
  • Exceptions represent problems you can handle in code. They come in two types:
    • Checked Exceptions: The compiler forces you to either catch them or declare them with throws. Example: IOException.
    • Unchecked Exceptions: The compiler does not require explicit handling. Example: ArithmeticException, NullPointerException.

Subsection 7.2.3 Which Should the Compiler Force Us to Handle?

Let’s test your understanding. Pause here! Write down your answers before continuing.
Question 1: Handling IOException (Checked)
Suppose a method needs to read data. The data might be invalid or missing. Should Java:
A) Force you to handle or declare IOException before running
B) Assume you’ll remember to check manually
Question 2: Handling ArithmeticException (Unchecked)
Suppose a method divides two numbers, and the divisor might be zero. Should Java:
A) Force the programmer to write try/catch around every division
B) Assume the programmer will fix or avoid dividing by zero
Think: What did you choose? Why?
Answers: For IOException, Java does (A)—it’s a checked exception. For ArithmeticException, Java does (B)—it’s unchecked, so you’re not forced to handle it at compile time. That’s the heart of checked vs. unchecked.

Subsection 7.2.4 Checked and Unchecked in Practice

Some failures, like a missing file or a network issue, are beyond our control. Java has a rule: if a method might fail in this way, it must warn whoever calls it. This is why we use throws IOException—it’s Java’s way of saying:
“Hey, something might go wrong! You need to handle this before running the program.”
Below is a partial implementation showing one method that might throw a checked exception, and another that can cause an unchecked exception:
(Before we see the answers, try to predict: What should the method do if y == 0? What kind of exception would make sense for readData()?)
public class ExceptionDemoSkeleton {

    // Checked exception example
    public static void readData() throws ??? {
        // What checked exception might we throw here?
        // e.g., throw new ???("Unable to read data...");
    }

    // Unchecked exception example
    public static int safeDivide(int x, int y) {
        // What if y == 0?
        // Return x / y or do a manual check?
        return ???;
    }
}
Think: Which standard checked exception could you throw? (Hint: IOException is a typical example for "something went wrong reading data.") And what should you do for safeDivide if y == 0?
Compare your answers with the full code below:
Notice that the compiler demands we handle or declare IOException but doesn’t require us to handle ArithmeticException. That’s the essence of checked vs. unchecked exceptions in action.

Subsection 7.2.5 Why throw new Exception(...) Is Too Generic

What’s wrong with this code? Before reading further, try to spot the mistake:
public static void setAge(int age) throws Exception {
    if (age < 0) {
        throw new Exception("Something went wrong!");
    }
    // ... proceed with setting age
}
This code compiles, but "Something went wrong!" doesn’t clearly say what the error is. It also forces a generic Exception onto the caller.
Here’s a better approach using a more specific, built-in type:
public static void setAge(int age) {
    if (age < 0) {
        // IllegalArgumentException is unchecked, but communicates exactly what happened
        throw new IllegalArgumentException("Age cannot be negative.");
    }
    // ... proceed with setting age
}
Now it’s clear to the caller that the argument was illegal. Specific exception types convey more meaning than a generic Exception.

Subsection 7.2.6 How to Handle Exceptions in Your Own Code

When You See a Checked Exception (IOException, SQLException):
  • The compiler won’t let you ignore it
  • You must use try/catch or declare throws
  • These usually mean something external went wrong (like a missing file)
When You Get an Unchecked Exception (NullPointerException, ArithmeticException):
  • These usually mean a bug in your code
  • Instead of catching them, fix the mistake that caused them
  • Common examples: dividing by zero, using null values
Best Practices for Your Code:
  • Never use throw new Exception(...)—it’s too vague
  • Choose specific exception types that clearly describe what went wrong
  • For dangerous operations (like division), check for invalid values first
  • When reading files or using networks, always handle checked exceptions
In Your Own Code, Remember:
  • Handle external failures (files, networks) using try/catch or throws
  • Avoid generic Exception—use a specific type like IllegalArgumentException
  • For invalid input, check manually before proceeding (e.g., don’t divide by zero)
  • If an error is a programmer mistake (like NullPointerException), fix the bug instead of catching it
That’s the essence of working with Java’s standard exceptions. Next up, we’ll continue exploring how to handle exceptions effectively (via try/catch and throws) so your programs never fail silently—and your code remains clear and predictable.

Exercises 7.2.7 Exercises

1. Multiple-Choice: Errors vs. Exceptions.

Which statement best describes the difference between Java Error and Exception classes?
  • Error represents critical system-level failures (e.g., OutOfMemoryError) that are usually not handled, while Exception represents problems your code can potentially catch and recover from.
  • Exactly. Error is generally fatal for the JVM, whereas Exception is recoverable.
  • They have no difference at runtime; Error is just a deprecated name for Exception.
  • No. Error is a distinct hierarchy for system-level issues.
  • Any Error is a compile-time issue, while Exception is always a runtime-only class.
  • No. Both occur at runtime; Error is not a compile-time phenomenon.
  • Error is for user input mistakes, while Exception is strictly for developer errors in code logic.
  • No. User input mistakes typically lead to Exceptions; Error signals bigger issues (like memory exhaustion).

2. Multiple-Choice: Checked vs. Unchecked Exceptions.

Which of the following correctly compares checked vs. unchecked exceptions in Java?
  • Checked exceptions are only caused by arithmetic operations (like dividing by zero), while unchecked exceptions come from external issues (like missing files).
  • No. It’s actually the opposite: dividing by zero triggers an ArithmeticException, which is unchecked.
  • Java forces you to handle or declare unchecked exceptions, but not checked ones.
  • No. It’s reversed. Checked exceptions must be handled or declared; unchecked do not require that.
  • Checked exceptions (e.g., IOException) must be caught or declared using throws, while unchecked exceptions (e.g., ArithmeticException) don’t require explicit handling.
  • Correct. That’s the fundamental difference in how Java treats checked vs. unchecked.
  • They are identical in behavior, but checked exceptions only happen at compile-time and unchecked happen at runtime.
  • No. All exceptions occur at runtime; "checked" means the compiler enforces handling.

3. Multiple-Choice: Dividing By Zero.

You have a method int divide(int x, int y) that does return x / y;. What happens if y is zero?
  • The compiler will refuse to compile your code unless you catch ArithmeticException.
  • No. ArithmeticException is unchecked, so the compiler doesn’t force you to catch it.
  • You automatically get a compile-time error, with no possibility of running the program.
  • No. There’s no compile-time error for dividing by a variable that might be zero.
  • The method returns 0 by default if y is zero.
  • No. It throws ArithmeticException at runtime; no default zero return is provided.
  • The program throws ArithmeticException at runtime if y is zero, terminating unless you catch it or avoid the division.
  • Correct. Since ArithmeticException is unchecked, it occurs at runtime with no compile-time warnings.

4. Multiple-Choice: Generic Exception.

Why might throw new Exception("Something went wrong!") be discouraged compared to throwing a more specific exception type?
  • Generic Exception causes Java to skip the catch block entirely, making the program terminate immediately.
  • No. Java doesn’t skip catch blocks if the type matches. The problem is lack of clarity.
  • It’s too vague. A more specific exception (e.g. IllegalArgumentException) conveys clearer intent, helping both the caller and any catch blocks respond appropriately.
  • Precisely. A specific exception type clarifies the exact nature of the error.
  • Throwing Exception is not valid Java code and won’t compile unless you add a final finally block.
  • No. It is valid code. The problem is that using a generic type is poor design, not compilation failure.
  • It’s not discouraged; in modern Java, Exception is always replaced automatically by RuntimeException at runtime.
  • No automatic replacement occurs. The developer must choose an appropriate type.
You have attempted of activities on this page.