What is the try-catch construct in Java, and how does the JVM decide which catch block handles a thrown exception?
answer
- Top-to-bottom, first assignable type wins
- At most one catch runs per throw
- Match by runtime type, not declared/static type
- No match -> propagate up the call stack
- Subtype IS-A supertype = assignable
basics
~20 sYou put risky code in a try block. If it throws, Java checks each catch block top to bottom and runs the first one whose declared type matches the thrown exception. If none match, the exception keeps propagating up.
solid answer
~40 sA try block wraps code that might throw an exception; one or more catch blocks follow it, each declaring an exception type it can handle. When code inside try throws, normal execution stops at that point and the JVM examines the catch clauses in source order, top to bottom. It selects the first clause whose declared type the thrown object is assignable to (the exact type or any supertype of it). That block runs, then execution continues after the whole try-catch. If no clause matches, the exception propagates out of the method to the caller, unwinding the stack until something catches it or it reaches the thread's top. Only the first matching catch runs, never several; matching is by the runtime type of the thrown object, not the static type of any variable.
go deeper
Can write a try-catch, name the parts, and state that the first matching catch (top-to-bottom) runs and execution then continues after the block.
Explains matching is assignability against the runtime type, that only one catch runs, and that an unmatched exception propagates up the call stack.
Articulates the subtype/supertype relationship driving the match, contrasts catching a specific type vs a family via a supertype, and reasons about propagation and stack unwinding.
Frames catch granularity as an API/error-handling design decision (recover at the right layer, avoid over-broad catches), and connects it to observability and failure-domain boundaries.
## What problem try-catch solves In Java, when something goes wrong at runtime (dividing by zero, calling a method on `null`, a file not existing), the running code creates an **exception object** and *throws* it. A thrown exception immediately interrupts normal step-by-step execution. Without a way to react, the exception would terminate the program. **try-catch** is the language construct that lets you intercept a thrown exception and run recovery code instead of crashing. ## The anatomy ``` try { // "guarded" code that might throw } catch (SomeExceptionType e) { // handler that runs if a matching exception is thrown } ``` - The **try block** holds the code you want to guard. - Each **catch clause** declares one exception **type** and a parameter name (`e`). The body runs only if a matching exception is thrown. - An exception object is an instance of a class. All exceptions descend from `java.lang.Throwable`; the everyday ones descend from `Exception`, and many runtime ones from `RuntimeException`. Because they form a class hierarchy, an exception object has a **type** *and* all of its **supertypes** (e.g. a `FileNotFoundException` *is also an* `IOException`, *is also an* `Exception`). ## How a match is decided When a statement inside `try` throws: 1. Normal execution stops at that statement. 2. The JVM looks at the catch clauses **in the order they appear in the source**, top to bottom. 3. For each clause it asks: *is the thrown object assignable to this clause's declared type?* "Assignable to" means the thrown object's class **is** that type or a **subclass** of it. This is exactly the `instanceof` relationship. 4. The **first** clause that matches is chosen. Its body runs. The remaining clauses are skipped — at most one catch ever runs per thrown exception. 5. After the handler finishes, control resumes at the statement **after** the entire try-catch (not back inside the try). If **no** clause matches, the exception is not handled here. It **propagates**: the current method exits abnormally and the same exception is re-thrown in the caller, which gets its own chance to catch it. This continues up the **call stack** until some method catches it or it reaches the thread's top, where the JVM prints a stack trace and (for the main thread) the program ends. ## Key subtlety: runtime type, not declared type Matching uses the **actual runtime class** of the thrown object, not the static type of any reference. If a method declared to return `Exception` actually throws a `NullPointerException` at runtime, a `catch (NullPointerException e)` clause will match it. ## Catching a family with a supertype Because matching follows subtype relationships, declaring a broad type catches a whole family. `catch (IOException e)` catches `FileNotFoundException`, `SocketException`, and every other `IOException` subclass with one clause. `catch (Exception e)` catches almost everything (every `Exception` subtype). This is convenient but blunt — see the ordering question and the red flags about catching too broadly. ## What's *not* covered here This unit is about plain `try`/`catch` matching. The `finally` block (always-run cleanup), multi-catch (`catch (A | B e)`), and try-with-resources are separate constructs.
- If no catch block matches, what happens to the exception?It propagates out of the current method to its caller, unwinding the stack method by method until a matching catch is found or it reaches the top of the thread, where the JVM prints a stack trace.
- Can two catch blocks run for a single thrown exception?No. Exactly one (the first matching clause) runs, or zero if none match. The others are skipped.
Catch blocks are like a row of mail sorters checked left to right; the letter (exception) drops into the first bin whose label it fits under, and once it lands the rest are ignored.
saying these in an interview costs you the question
- Thinking all matching catch blocks run, or that they are tried bottom-to-top
- Believing the match is on a variable's declared type rather than the object's runtime class
- Assuming an unmatched exception is silently swallowed instead of propagating