Handling Exceptions practice questions

From OCP Java SE 17 (1Z0-829) · 19 questions on this topic

Handling Exceptions practice questions from OCP Java SE 17 (1Z0-829). This pack has 19 questions tagged Handling Exceptions, drawn from its timed mock exams. 8 of them are worked through in full below — the question, every option, why each is right or wrong, and the explanation.

Worked examples for Handling Exceptions

  1. Question 1

    What does this print? ```java public class Main { static class R implements AutoCloseable { public void close() { System.out.print("close "); } } public static void main(String[] args) { try (R r = new R()) { System.out.print("body "); throw new IllegalStateException(); } catch (RuntimeException e) { System.out.print("catch "); } finally { System.out.print("finally"); } } } ```

    1. A. body close catch finallyCorrect answer

      The body runs and throws, the resource's implicit close() runs immediately as the try block is exited, then the matching catch handles the exception, and finally runs last (JLS 17 §14.20.3).

    2. B. body catch close finally

      close() cannot run after the catch; the resource is released as part of leaving the try block, so the handler already sees a closed resource.

    3. C. body catch finally close

      Same flaw — the implicit close() happens on exit from the try, never after the catch or finally.

    4. D. body close finally catch

      The catch clause always runs before the finally block; that order never inverts.

    Explanation

    When a try-with-resources body throws, the resource is closed first: the implicit close() runs as control leaves the try block, before any catch or finally of the same statement. Only after the resource is released does the matching catch handle the exception, and the finally block runs last of all. Because close() precedes the catch, any code in the catch that touches the resource is using one that is already closed (JLS 17 §14.20.3).

  2. Question 2

    What must be true of a variable used as a resource in try-with-resources without re-declaring it?

    1. A. It must be final or effectively final and of a type implementing AutoCloseableCorrect answer

      Since Java 9 a try-with-resources header may name an existing variable rather than declaring a new one, provided that variable is final or effectively final and its type implements AutoCloseable (JLS 17 §14.20.3).

    2. B. Only newly-constructed resources may be used; existing variables are not allowed

      Pre-existing variables are permitted as resources; the restriction that required a freshly declared resource ended with Java 8.

    3. C. It must be re-declared inside the try header

      Re-declaring a new resource in the header is the alternative form, not a requirement — an existing effectively-final variable can be used as-is.

    4. D. It must be declared volatile

      volatile is a field modifier for cross-thread visibility and cannot even be applied to a local variable; it has nothing to do with resource eligibility.

    Explanation

    From Java 9 onward, a try-with-resources statement can reference a previously declared variable directly in its header instead of declaring a new resource. The only requirements are that the variable be final or effectively final — never reassigned after initialization — and that its type implement AutoCloseable. Reassigning the variable before the try would break effective finality and stop the code compiling (JLS 17 §14.20.3).

  3. Question 3

    Which two statements about checked and unchecked exceptions are correct? (Choose two.)

    1. A. RuntimeException and its subclasses are unchecked and need not be caught or declaredCorrect answer

      RuntimeException and its subclasses are unchecked, so the compiler never requires that they be caught or declared (JLS 17 §11.1.1).

    2. B. Error and its subclasses must be declared in a throws clause when a method can raise them

      Error and its subclasses are unchecked precisely because callers cannot reasonably recover, so no throws declaration is required.

    3. C. IOException is checked: code that can throw it must catch it or declare itCorrect answer

      IOException does not descend from RuntimeException or Error, so it is checked: a method that can throw it must either catch it or list it in a throws clause.

    4. D. Checked exceptions are the ones that extend RuntimeException

      This is inverted — extending RuntimeException makes an exception unchecked; checked exceptions extend Exception without passing through RuntimeException.

    Explanation

    The unchecked exception classes are RuntimeException and Error together with their subclasses; the compiler never forces a caller to catch or declare them. Every other class under Throwable is checked, which is why a method that can raise IOException must catch it or declare it in a throws clause. Extending RuntimeException makes an exception unchecked, not checked (JLS 17 §11.1.1).

  4. Question 4

    Both the try body and close() throw. The catch block inspects the exception it received. What is printed? ```java public class Main { static class R implements AutoCloseable { @Override public void close() { throw new IllegalStateException("close"); } } public static void main(String[] args) { try (R r = new R()) { throw new RuntimeException("body"); } catch (Exception e) { Throwable[] s = e.getSuppressed(); System.out.println(e.getMessage() + " " + s.length + " " + s[0].getMessage()); } } } ```

    1. A. body 1 closeCorrect answer

      Correct — the body's exception propagates as primary and the close() exception is attached as a suppressed exception, so the caught message is "body" and the single suppressed message is "close".

    2. B. close 1 body

      Inverts the roles; that ordering would occur only if the body completed normally and close() alone threw, making close() the primary exception.

    3. C. Throws IllegalStateException

      Assumes the close() exception propagates uncaught; it is instead suppressed and attached to the primary body exception, which is caught.

    4. D. Throws ArrayIndexOutOfBoundsException

      Assumes the suppressed array is empty; the close() exception is recorded as one suppressed element, so index 0 exists.

    Explanation

    When the try body throws and the resource's close() also throws, the body's exception is the one that propagates and the close() exception is attached to it as a suppressed exception rather than replacing it. The catch therefore receives the body's exception, and its suppressed array holds exactly the close() exception.

  5. Question 5

    The constructor of the SECOND resource throws. What does this program print? ```java public class Main { static class R implements AutoCloseable { private final String n; R(String n) { this.n = n; System.out.print("open" + n + " "); if (n.equals("B")) { throw new IllegalStateException("boom"); } } @Override public void close() { System.out.print("close" + n + " "); } } public static void main(String[] args) { try (R a = new R("A"); R b = new R("B")) { System.out.print("body "); } catch (Exception e) { System.out.print("caught"); } } } ```

    1. A. openA openB body closeA caught

      Wrong: this assumes the body runs anyway. That is the behaviour of a resource that evaluates to null (body runs, close skipped), not of a resource initializer that throws - here the body is skipped entirely.

    2. B. openA openB caught

      Wrong: this assumes a failure in the header closes nothing, which would leak the resource already opened - precisely what try-with-resources exists to prevent. The initialized first resource is still closed.

    3. C. openA openB closeB closeA caught

      Wrong: this assumes a resource whose constructor threw still gets closed. The second resource variable was never assigned, so close() cannot be invoked on it; only resources whose initializer completed normally are closed.

    4. D. openA openB closeA caughtCorrect answer

      Correct: the second constructor prints openB then throws before b is assigned, so the body is skipped and only the successfully initialized first resource is closed (closeA), then the exception is caught.

    Explanation

    Trace: resource initializers run left to right. `new R("A")` succeeds and prints `openA `, so a is an initialized resource. `new R("B")` prints `openB ` and then throws, so b is NEVER successfully initialized. The try BODY does not run at all — it is only entered once every resource in the header is initialized. Java then closes the resources that were successfully initialized, in reverse order: only a qualifies, so `closeA ` prints. b's close() is not called: there is no object to close it on. The IllegalStateException propagates out of the header and is caught, printing `caught`. Why the others are wrong: `openA openB closeB closeA caught` assumes a resource whose constructor threw still gets closed. The resource variable was never assigned, so close() cannot be invoked on it — close() is only called for resources whose initializer completed normally. `openA openB caught` assumes a failure anywhere in the header abandons the whole statement without closing anything, which would leak the resource that was already open — precisely what try-with-resources exists to prevent. `openA openB body closeA caught` assumes the body runs anyway. That is the behaviour of a resource that evaluates to null (body runs, close skipped), not of a resource initializer that throws. Exam tip: split try-with-resources into header, body, close. If the header throws part-way, the body is skipped entirely and exactly the resources already initialized are closed, in reverse order. The reverse trap: `try (R r = null)` — the initializer completed normally, so the body DOES run, and close() is simply skipped on the null reference.

  6. Question 6

    Consider a try-with-resources statement whose resources implement AutoCloseable. Which two statements are correct? (Choose two.)

    1. A. Resources are closed in declaration order, so the resource declared first is closed first

      Wrong: this inverts the rule. Resources are closed in reverse of declaration order, so a later resource that may depend on an earlier one is closed first.

    2. B. If the try body completes normally and close() throws, that exception propagates from the try statement and may be handled by a catch clause of the same statementCorrect answer

      Correct: the implicit close() calls run before any catch clause of the same statement is considered, so an exception close() raises is still inside that statement and its own catch clauses get first refusal.

    3. C. If a resource's close() is declared throws Exception, the try-with-resources must catch or declare that exception even when the body throws nothingCorrect answer

      Correct: try-with-resources performs catch-or-declare analysis on the implicit close() call, so a resource whose close() is declared throws Exception forces handling even when the body throws nothing.

    4. D. When both the body and close() throw, the exception from close() is the one that propagates and the body's exception is added to its suppressed list

      Wrong: this inverts primary and suppressed. When both throw, the body's exception is the primary one that propagates and close()'s exception is added to it via addSuppressed, never the other way round.

    Explanation

    Why `If the try body completes normally and close() throws...` is correct: the implicit close() calls happen before any catch clause of the same try statement is considered, so an exception they raise is still 'inside' that statement and its own catch clauses get first refusal. A resource whose close() throws IllegalStateException("fromClose") inside a try body that completed normally is caught by a catch (IllegalStateException e) on that very statement, with an empty suppressed array. Why `If a resource's close() is declared throws Exception...` is correct: try-with-resources performs catch-or-declare analysis on the IMPLICIT close() call, not just on the body. A resource type whose close() is declared `throws Exception`, used with a body that throws nothing and no catch clause, is a compile error: `unreported exception Exception; must be caught or declared to be thrown` — javac even points at the resource and says the exception is thrown from the implicit call to close(). Adding catch (Exception e) makes it compile. This is exactly why closing a java.io.Reader forces you to handle IOException. Why the others are wrong: `Resources are closed in declaration order...` inverts the rule. Closing is reverse of declaration — three resources declared first, second, third close third, second, first — because a later resource may depend on an earlier one (a Reader wrapping a stream must close before the stream). `When both the body and close() throw...` inverts primary and suppressed. The BODY's exception is the primary one that propagates; close()'s exception is attached to it via addSuppressed and is reachable only through getSuppressed(). The body's exception is the one the developer cares about, so the language never lets a cleanup failure hide it. Exam tip: the ordering rule and the primary/suppressed rule are the two most-tested facts here, and both are easy to state backwards. Anchor them on intent — close in reverse so dependencies unwind safely, and never let a close() failure mask the real failure.

  7. Question 7

    A helper method returns a different code from each catch clause and prints a marker in finally. What is the result of compiling and running this program? ```java import java.io.FileNotFoundException; import java.io.IOException; public class Main { static int read(boolean missing) { try { if (missing) { throw new FileNotFoundException("nf"); } throw new IOException("io"); } catch (IOException e) { return 1; } catch (FileNotFoundException e) { return 2; } finally { System.out.print("f "); } } public static void main(String[] args) { System.out.println(read(true)); } } ```

    1. A. f 2

      Assumes the most-specific handler wins; catch clauses are matched top-down, and since FileNotFoundException is a subclass of the already-caught IOException, its clause is unreachable and the code does not compile.

    2. B. f 1

      Assumes the code compiles and the IOException clause handles the FileNotFoundException; the unreachable second catch is a compile error, so nothing runs.

    3. C. 2

      Assumes the more specific clause runs and there is no finally output; the program never compiles because the FileNotFoundException catch is unreachable.

    4. D. Compilation failsCorrect answer

      Correct — FileNotFoundException is a subclass of IOException, so the second catch is unreachable, which is a compile-time error (JLS 17 §11.2.3).

    Explanation

    FileNotFoundException is a subclass of IOException, so the second catch clause is unreachable: it is a compile-time error for a catch clause to catch a checked exception type that a preceding catch clause of the same try already catches (JLS 17 §11.2.3) — javac reports 'exception FileNotFoundException has already been caught'. Catch clauses are matched top-down in source order, not most-specific-first, so the intuition behind 'f 2' (the more specific handler wins) is precisely the misconception being tested; the fix is to list the subclass first.

  8. Question 8

    What does this print? ```java public class Main { static class R implements AutoCloseable { public void close() { throw new RuntimeException("close"); } } public static void main(String[] args) { try (R r = new R()) { throw new RuntimeException("body"); } catch (Exception e) { System.out.print(e.getMessage()); for (Throwable t : e.getSuppressed()) System.out.print("+" + t.getMessage()); } } } ```

    1. A. close

      This would mean the close() exception replaced the body's exception, but suppression exists precisely so the primary exception is not lost.

    2. B. body

      This ignores the suppressed array, which the code explicitly iterates and prints, so the close() message must also appear.

    3. C. body+closeCorrect answer

      The body's exception propagates as the primary exception and the close() exception is attached to it via addSuppressed, so the primary message prints first, followed by the suppressed message (JLS 17 §14.20.3).

    4. D. close+body

      The roles are fixed — the body's exception is primary and the close() exception is the suppressed one — so the order can never be reversed.

    Explanation

    When a try-with-resources body throws and the automatic close() also throws, the body's exception is the primary one that propagates, and the close() exception is attached to it as a suppressed exception rather than replacing it. Code can retrieve those secondary exceptions through getSuppressed(). This is the opposite of a finally block, where an exception thrown in finally replaces the original (JLS 17 §14.20.3).

Practise all 19 Handling Exceptions questions

OCP Java SE 17 has the full set, inside timed mock exams that mirror real exam conditions — every question with a worked explanation.

Open OCP Java SE 17

Other topics in this pack