Register

Java for Beginners

0 of 24 notes read 0%

Reading progress is saved to your INFIRALS account. Sign in to keep this note marked as read.

Checked, unchecked, and throwing

Exceptions, collections and modern Java11 min readLesson 2 of 6

2.1 Two families

Checked exceptions are checked by the compiler. A method that can throw one must declare it with throws or handle it with try/catch. IOException and SQLException are common examples.

Unchecked exceptions extend RuntimeException. The compiler does not require a declaration. NullPointerException, IllegalArgumentException, and ArithmeticException belong here.

The split is about recovery. A checked exception marks a condition the caller may be able to handle, such as a missing file. An unchecked exception usually marks a bug or a violated precondition.

java
import java.io.IOException;

public class Main {
    public static void main(String[] args) {
        try {
            readConfig();
        } catch (IOException e) {
            System.out.println("Failed: " + e.getMessage());
        }
    }
    static void readConfig() throws IOException {
        throw new IOException("Missing file");
    }
}

Output

Failed: Missing file

2.1.1 throw and throws

throw raises an exception object at a point in the code. throws appears in a method signature and lists the checked exceptions that may leave the method. The two words are related but do different jobs.

throw new IllegalArgumentException("Age cannot be negative"); fails fast when a precondition is broken. The message should name the value or rule that failed, without exposing secrets.

A method can declare several checked exceptions, separated by commas. The caller must handle them or pass the responsibility up the chain.

java
public class Main {
    public static void main(String[] args) {
        try {
            setAge(-3);
        } catch (IllegalArgumentException e) {
            System.out.println(e.getMessage());
        }
    }
    static void setAge(int age) {
        if (age < 0) {
            throw new IllegalArgumentException("Age cannot be negative");
        }
        System.out.println("Age: " + age);
    }
}

Output

Age cannot be negative

2.1.2 Custom exceptions

Extend Exception for a checked custom exception, or RuntimeException for an unchecked one. A class name such as InsufficientFundsException tells the caller what went wrong.

A custom exception can carry data, such as the missing amount. Add a constructor that passes a message to super(...) and a getter for the extra field. Keep the class small.

Use a custom type when callers need to distinguish the failure from other exceptions. If a standard type already conveys the meaning, use it.

java
public class Main {
    public static void main(String[] args) {
        try {
            withdraw(100, 150);
        } catch (InsufficientFundsException e) {
            System.out.println(e.getMessage());
        }
    }
    static void withdraw(int balance, int amount) throws InsufficientFundsException {
        if (amount > balance) {
            throw new InsufficientFundsException("Short by " + (amount - balance));
        }
    }
}
class InsufficientFundsException extends Exception {
    InsufficientFundsException(String message) {
        super(message);
    }
}

Output

Short by 50

2.1.3 try-with-resources

A resource that implements AutoCloseable can be declared in the parentheses of a try-with-resources statement. The JVM calls close() automatically when the block ends, including when an exception is thrown.

try (Scanner scanner = new Scanner(file)) { ... } closes the scanner without a finally block. Several resources can be declared in one try, separated by semicolons, and they close in reverse order.

The resource variable is scoped to the try block. Code outside the block cannot use it, which prevents work with a closed resource.

java
public class Main {
    public static void main(String[] args) {
        try (Session session = new Session()) {
            session.use();
        }
        System.out.println("Closed");
    }
}
class Session implements AutoCloseable {
    void use() { System.out.println("Using"); }
    @Override
    public void close() { System.out.println("Closing"); }
}

Output

Using
Closing
Closed

2.1.4 Validation and rethrow

Validate arguments at the start of a method and throw an unchecked exception for a broken contract. That keeps the error close to its cause, so a bad value does not travel through several calls.

A catch block can log and rethrow when the method cannot recover but the caller might. throw e; preserves the original exception. Wrapping it in another exception can add context, and the original becomes the cause.

Avoid catching Exception only to print a message. A broad catch hides the type and makes the caller's handling less precise.

java
public class Main {
    public static void main(String[] args) {
        try {
            parse("12");
            parse("oops");
        } catch (NumberFormatException e) {
            System.out.println("Stopped at bad input");
        }
    }
    static int parse(String text) {
        return Integer.parseInt(text);
    }
}

Output

Stopped at bad input

2.1.5 Practice

  1. Write a method that declares throws Exception, throw from it, and handle the call in main.
  2. Throw IllegalArgumentException from a validation method and print the message in a catch.
  3. Create a custom checked exception with a message and throw it when a withdrawal exceeds the balance.
  4. Create a class that implements AutoCloseable and confirm that close runs after the try block.
  5. Parse two strings in one try, let the second throw, and note that the statement after it never runs.

For step 4, print one line in the try block and one in close(). The order in the output shows the cleanup path.

Interview questions

3 questions from this note. Open one to see the answer; no account needed.

  • 01What makes an exception checked?

    It is not a subclass of `RuntimeException` or `Error`, so the compiler requires the method to declare it with `throws` or handle it.

  • 02What is the difference between `throw` and `throws`?

    `throw` raises an exception object inside a method. `throws` lists the checked exceptions a method may pass to its caller.

  • 03How does try-with-resources close a resource?

    It calls `close()` automatically when the block exits, including on an exception. The resource must implement `AutoCloseable`.