Menu
Coddy logo textTech

Checked vs Unchecked Errors

Part of the Object Oriented Programming section of Coddy's Java journey — lesson 61 of 87.

You've seen that Java's exception hierarchy splits into different branches. The key distinction you need to understand is between checked and unchecked exceptions—this affects how you must handle them in your code.

Checked exceptions are exceptions that the compiler forces you to handle. They extend Exception directly (not through RuntimeException). You must either catch them or declare them with throws:

// Must handle IOException - it's checked
public void readFile(String path) throws IOException {
    FileReader reader = new FileReader(path);  // May throw IOException
}

// Or catch it
public void readFileSafe(String path) {
    try {
        FileReader reader = new FileReader(path);
    } catch (IOException e) {
        System.out.println("File error: " + e.getMessage());
    }
}

Unchecked exceptions extend RuntimeException. The compiler doesn't require you to handle them—they typically indicate programming errors like null references or invalid array access:

// No throws declaration needed
public int divide(int a, int b) {
    return a / b;  // May throw ArithmeticException (unchecked)
}

String name = null;
name.length();  // NullPointerException (unchecked)

When creating custom exceptions, choose the parent class based on how you want callers to handle them. Use checked exceptions for recoverable conditions the caller should anticipate. Use unchecked exceptions for programming errors that shouldn't occur in correct code.

challenge icon

Challenge

Easy

Let's build an age verification system that demonstrates the key difference between checked and unchecked exceptions! You'll create custom exceptions of both types and see how the compiler treats them differently.

You'll organize your code across four files:

  • InvalidAgeException.java: Create a checked exception for age validation failures. This exception should extend Exception directly, meaning callers will be forced to handle it. Include a constructor that accepts a message and passes it to the parent class.
  • NegativeAgeException.java: Create an unchecked exception for when someone provides a negative age (a programming error that shouldn't happen with correct input). This should extend RuntimeException. Include a constructor that accepts and passes a message to the parent.
  • AgeVerifier.java: Create a class that validates ages using both exception types. Include two static methods:

    verifyAge(int age) - This method should throw NegativeAgeException (unchecked) with message "Age cannot be negative: [age]" if the age is less than 0. If the age is less than 18, throw InvalidAgeException (checked) with message "Must be 18 or older: [age]". Otherwise, print Age [age] verified successfully. Since this method throws a checked exception, you must declare it with throws InvalidAgeException.

    verifyAgeUncheckedOnly(int age) - This method only uses unchecked exceptions. If age is negative, throw NegativeAgeException with the same message format. If age is less than 18, throw an IllegalArgumentException with message "Too young: [age]". Otherwise, print Age [age] verified (unchecked method). Notice this method needs no throws declaration!

  • Main.java: Bring your verification system together! You'll receive one input: an age (integer).

    First, print === Checked Exception Method === and call verifyAge with the input age. Since it throws a checked exception, you must wrap it in a try-catch. Catch InvalidAgeException and print Checked exception caught: [message]. Also catch NegativeAgeException and print Unchecked exception caught: [message].

    Then print a blank line and === Unchecked Exception Method ===. Call verifyAgeUncheckedOnly with the same age. Even though this method can throw exceptions, you're not forced to catch them. However, wrap it in a try-catch anyway to handle errors gracefully. Catch NegativeAgeException and print Runtime exception caught: [message]. Catch IllegalArgumentException and print Illegal argument caught: [message].

You will receive one input: an integer representing the age to verify.

Notice the key difference: the method with the checked exception requires a throws declaration and forces callers to handle it, while the unchecked method compiles fine without any exception handling. This is the fundamental distinction between checked and unchecked exceptions in Java!

Cheat sheet

Java exceptions are divided into checked and unchecked exceptions, which determines how the compiler enforces handling them.

Checked exceptions extend Exception directly (not through RuntimeException). The compiler forces you to either catch them or declare them with throws:

// Must declare with throws
public void readFile(String path) throws IOException {
    FileReader reader = new FileReader(path);
}

// Or catch it
public void readFileSafe(String path) {
    try {
        FileReader reader = new FileReader(path);
    } catch (IOException e) {
        System.out.println("File error: " + e.getMessage());
    }
}

Unchecked exceptions extend RuntimeException. The compiler doesn't require you to handle them. They typically indicate programming errors:

// No throws declaration needed
public int divide(int a, int b) {
    return a / b;  // May throw ArithmeticException (unchecked)
}

String name = null;
name.length();  // NullPointerException (unchecked)

When creating custom exceptions, choose the parent class based on how callers should handle them:

  • Use checked exceptions (extend Exception) for recoverable conditions the caller should anticipate
  • Use unchecked exceptions (extend RuntimeException) for programming errors that shouldn't occur in correct code

Try it yourself

import java.util.Scanner;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int age = scanner.nextInt();
        
        // TODO: Test the checked exception method
        // Print: "=== Checked Exception Method ==="
        // Call AgeVerifier.verifyAge(age) in a try-catch
        // - Catch InvalidAgeException: print "Checked exception caught: [message]"
        // - Catch NegativeAgeException: print "Unchecked exception caught: [message]"
        
        
        // TODO: Print a blank line, then "=== Unchecked Exception Method ==="
        // Call AgeVerifier.verifyAgeUncheckedOnly(age) in a try-catch
        // - Catch NegativeAgeException: print "Runtime exception caught: [message]"
        // - Catch IllegalArgumentException: print "Illegal argument caught: [message]"
        
    }
}
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Object Oriented Programming