Skip to content

Exceptions

Exceptions transfer control when a method cannot fulfill its normal contract. They should describe failures, not replace ordinary branching.

Checked and unchecked

  • checked exceptions must be caught or declared and can describe recoverable conditions a caller is expected to consider;
  • RuntimeException subclasses commonly signal programming errors, invalid arguments, illegal state, or failures impractical to recover from locally;
  • Error generally represents serious runtime conditions application code should not routinely catch.

This taxonomy does not decide an API automatically. Consider whether callers can meaningfully recover, whether the failure is part of the abstraction, and how the API composes.

Preserve context

static String readUtf8(Path path) {
    try {
        return Files.readString(path, StandardCharsets.UTF_8);
    } catch (IOException cause) {
        throw new UncheckedIOException("failed to read " + path, cause);
    }
}

Wrapping preserves the cause. Messages should add actionable context without including secrets or sensitive contents.

Resource safety

Use try-with-resources for AutoCloseable values. It closes resources in reverse declaration order and preserves close failures as suppressed exceptions when another exception is already propagating.

Practices

  • catch the narrowest exception you can handle;
  • do not log and rethrow at every layer;
  • restore the interrupt status or propagate InterruptedException when a layer cannot complete the cancellation policy;
  • avoid returning null merely to hide failure;
  • translate low-level exceptions at abstraction boundaries while retaining cause.