Skip to content

Exception handling

Exceptions are Java’s way of signaling that something went wrong (invalid input, missing resource, unsupported operation, etc.). If not handled, they can stop the program.

Stage 1core2 min read

What are exceptions?

Sometimes a method cannot do its job. The input is bad, a file is missing, or an action is not allowed. It needs a way to say so. An exception is an object that describes the problem and stops the normal flow of the method. Code can signal one with throw and handle it with catch. Or it can let the exception travel up the call stack (the chain of methods that called each other).

Throwing means: “I cannot finish. Someone at this level or above must decide what to do.” If nobody catches it, the current request or the whole program can end.

Key ideas

  • throw new SomeException("message"): create and throw an exception. Control leaves the method until something catches it.
  • try { ... } catch (ExceptionType e) { ... }: run the code in try. If it throws that exception type, run the catch block instead. There you can log the error, turn it into another exception, or return a default value.
  • Checked vs unchecked: Some exceptions, such as CloneNotSupportedException, are “checked.” The compiler forces you to either handle them or add throws to the method signature. Runtime exceptions, such as IllegalArgumentException and UnsupportedOperationException, are “unchecked.” The compiler does not force anything.

Example: handling (try/catch)

@Override
public WelcomeEmail clone() {
    try {
        return (WelcomeEmail) super.clone();
    } catch (CloneNotSupportedException e) {
        throw new RuntimeException("Clone failed", e);
    }
}
  • super.clone() can throw CloneNotSupportedException (checked). We catch it and wrap it in a RuntimeException (unchecked), with the original error e kept inside. Callers need no throws.

Example: throwing (signaling error)

public static Logistics getLogistics(String mode) {
    if (mode.equalsIgnoreCase("Air")) {
        return new Air();
    } else if (mode.equalsIgnoreCase("Road")) {
        return new Road();
    }
    throw new IllegalArgumentException("Unknown logistics mode: " + mode);
}
// LSP/ISP bad examples: unsupported operation
@Override
public void write() {
    throw new UnsupportedOperationException("Can't write to a read-only file");
}
  • First: the argument is invalid (for example "train"), so throw IllegalArgumentException. The code only reaches the throw if neither branch matched.
  • Second: this type does not allow the operation, so throw UnsupportedOperationException.

Where you see it in this repo

  • Prototype: clone() in try-catch for CloneNotSupportedException.
  • Factory / Abstract Factory: IllegalArgumentException for unknown mode or unsupported region.
  • OCP BadCode: IllegalArgumentException for unsupported payment method.
  • LSP/ISP BadCode: UnsupportedOperationException when a method is not supported, such as write on a read-only file or scan on a simple printer.

In this topic

Done with this topic?

How well do you know it?

PreviousGenerics