skip to content

What is the throws clause in Java, and what does the compiler's 'catch-or-declare' rule require?

level: juniorimportance: must knowfreq 70%

answer

  1. throws = signature lists possible escaping exceptions
  2. Checked => catch OR declare, enforced by compiler
  3. Unchecked (RuntimeException/Error) are exempt
  4. Obligation cascades up the call stack
  5. Reaches main => thread dies if never handled

basics

~10 s

The throws clause lists exceptions a method might throw. For checked exceptions Java forces you to either handle them with try/catch or declare them with throws, so callers know to deal with them.

solid answer

~40 s

The throws clause is part of a method signature that names the exception types the method may propagate to its caller, e.g. void read() throws IOException. For checked exceptions the compiler enforces 'catch-or-declare': inside a method, any checked exception that can be thrown must either be caught with a try/catch block or declared in the method's throws clause. This pushes the obligation up to the caller, who then faces the same choice. The goal is that recoverable, expected failure conditions are visible in the API and cannot be silently ignored at compile time. Unchecked exceptions (RuntimeException and Error and their subclasses) are exempt: they need not be declared or caught, though you may still list them in throws for documentation.

go deeper

for a junior

Knows throws lists exceptions and that checked exceptions must be caught or declared; can read the compiler error and fix it by adding throws or a try/catch.

for a middle

Articulates the checked/unchecked split precisely (RuntimeException/Error exempt), explains the cascading obligation up the stack, and chooses catch vs. declare based on whether this layer can recover.

for a senior

Reasons about API design: what to expose in throws, when to translate checked to unchecked, the cost of declaring overly broad supertypes, and how the rule interacts with team conventions.

for a principal

Frames catch-or-declare as a contract-design and error-handling-strategy decision across a codebase; weighs checked exceptions vs. the industry shift toward unchecked, and the maintainability tradeoffs of each.

## What this is about In Java, an **exception** is an object representing an abnormal event (a file is missing, a number can't be parsed). When code 'throws' an exception, normal execution stops and Java looks for a matching `catch` block up the call stack. The **`throws` clause** is the part of a method's signature that announces which exception types a method might let escape to whoever called it. ```java void loadConfig() throws IOException { ... } ``` This says: "calling `loadConfig()` might result in an `IOException`." ## Checked vs. unchecked exceptions Java splits exceptions into two families based on their class: - **Checked exceptions**: subclasses of `Exception` that are **not** subclasses of `RuntimeException` (e.g. `IOException`, `SQLException`). The compiler *checks* that you deal with them. - **Unchecked exceptions**: subclasses of `RuntimeException` (e.g. `NullPointerException`, `IllegalArgumentException`) and subclasses of `Error` (e.g. `OutOfMemoryError`). The compiler does **not** check these. The whole `throws`/catch-or-declare machinery applies **only to checked exceptions**. ## The catch-or-declare requirement For every checked exception that a piece of code *can* throw, the enclosing method must do one of two things, or the code will not compile: 1. **Catch it** — surround the risky call in a `try` block with a matching `catch`: ```java void run() { try { loadConfig(); } catch (IOException e) { // handle or recover } } ``` 2. **Declare it** — add the exception type to the method's own `throws` clause, passing the obligation to the caller: ```java void run() throws IOException { loadConfig(); } ``` This is sometimes called 'catch or specify'. The obligation cascades: if `run()` declares `IOException`, then *its* caller must again catch or declare. Eventually some method handles it or it reaches `main` and terminates the thread. ## Why unchecked exceptions are exempt Unchecked exceptions usually signal **programming bugs** (dereferencing null, bad array index) that could happen at almost any line. Forcing a declaration on every method would be noise. So `RuntimeException` and `Error` need not be declared or caught; you *may* still list a `RuntimeException` in `throws` purely as documentation, but it changes nothing the compiler enforces. ## What 'can be thrown' means A method 'can throw' a checked exception E if it contains a `throw` statement of type E (or a subtype), or calls another method that *declares* E. So declarations propagate transitively through the `throws` clauses you call. ## Multiple exceptions A `throws` clause can list several comma-separated types: `throws IOException, SQLException`. You may also declare a common supertype (e.g. `throws Exception`) to cover several at once, though that's coarse and hides detail from callers. ## Common mistakes the compiler catches - Calling a method that declares a checked exception without catching or declaring it → compile error: 'unreported exception ... must be caught or declared'. - Declaring a checked exception that the method body can never actually throw → for *checked* types this is a compile error in a `catch` clause (you can't catch an exception that's never thrown), but a redundant `throws` declaration of a never-thrown checked exception is allowed and harmless. ## Deriving the answer at any level Given all the above: the `throws` clause documents-and-enforces the contract for *recoverable, anticipated* failures; the compiler guarantees a caller is aware of them. Unchecked exceptions opt out because they model bugs and would otherwise pollute every signature.

  • If method A calls method B which declares IOException, and A neither catches nor declares it, what happens?
    A fails to compile with 'unreported exception IOException; must be caught or declared to be thrown'. A must either wrap the call in a try/catch for IOException or add IOException to its own throws clause.
  • Can you put a RuntimeException in a throws clause?
    Yes, it's legal and sometimes done for documentation, but the compiler doesn't enforce anything for it — callers are not required to catch or declare it.

saying these in an interview costs you the question

  • Claiming throws actually throws the exception (it only declares it)
  • Saying all exceptions must be declared — unchecked ones need not be
  • Confusing throws (declaration) with throw (the statement that raises one)
  • Thinking declaring an exception means the method definitely throws it

context