- Which statement correctly explains why
launch can compile without a try statement or throws clause? Answer: ShutdownSignal is unchecked because subclasses of Error are exempt from catch-or-declare.
When you see a question about whether a method needs a try block or throws clause, your first instinct should be to classify the exception type: checked or unchecked? Java's "catch-or-declare" rule only applies to checked exceptions — unchecked ones can propagate freely without any special handling.
Java divides Throwable into three categories: Exception subclasses (checked, unless they extend RuntimeException), RuntimeException subclasses (unchecked), and Error subclasses (unchecked). ShutdownSignal extends Error, which places it squarely in the unchecked category. Because it's unchecked, neither stopNow nor launch is required to declare or handle it — that's exactly why D is correct. The JVM makes Error and its subclasses exempt from catch-or-declare because they typically represent serious, unrecoverable system-level problems (like OutOfMemoryError) that most code shouldn't be expected to handle.
A is wrong on two counts: ShutdownSignal is not checked, and there's no such thing as "automatic JVM declaration" for checked errors. B is wrong because it incorrectly calls ShutdownSignal checked and also misrepresents the catch-or-declare rule — all methods in the call chain must declare checked exceptions, not just the one that directly throws them. C contains a fundamental misconception: not every Throwable subclass is a runtime exception. RuntimeException is a specific branch of the hierarchy, and extending Error does not make something a runtime exception.
A reliable memory aid: think of the hierarchy as **Checked = plain Exception subclasses, Unchecked = RuntimeException or Error subclasses**. If it extends Error, catch-or-declare never applies.
- What is the compilation result for
forward? Answer: It compiles because precise rethrow analysis limits ex to the declared alternatives.
When you see a question involving rethrowing a caught exception, think about precise rethrow analysis — a feature introduced in Java 7 that allows the compiler to be smarter about what types are actually being rethrown.
Here's the key insight: when you catch a broad type like Exception and rethrow that variable, the compiler doesn't blindly assume you're throwing Exception. Instead, it analyzes which specific exceptions could have been thrown inside the try block. In forward, the only call is process(), which declares throws IOException, SQLException. So the compiler knows ex can only ever be an IOException or a SQLException at runtime. Because forward already declares throws IOException, SQLException, rethrowing ex is perfectly legal — no throws Exception needed. D is correct.
A describes the naive interpretation — that catching Exception ex and rethrowing it forces you to declare throws Exception. This was true before Java 7, but precise rethrow analysis makes it incorrect for this code. B is simply fabricated; Java has no rule restricting rethrows to multi-catch clauses (catch (X | Y ex)). Multi-catch is a separate convenience feature. C is factually wrong on two levels: IOException and SQLException are checked exceptions (subclasses of Exception, not RuntimeException), and whether something compiles here has nothing to do with being a RuntimeException.
As a study tip, remember: precise rethrow means the compiler tracks what can actually enter the catch block, not just the declared catch type. If the try body only throws checked exceptions already covered by the method's throws clause, rethrowing a broad variable is still valid.
- Which change is sufficient to make
validate compile without changing either exception class? Answer: Add throws DataProblem to the declaration of validate.
When you see a question about checked vs. unchecked exceptions in Java, your first step is to categorize each exception being thrown. Checked exceptions (those extending Exception but not RuntimeException) must be declared in the method signature or caught — the compiler enforces this. Unchecked exceptions (extending RuntimeException) require neither.
In validate, BadData extends DataProblem, which extends Exception — making it a checked exception. That's the compilation problem: the method throws BadData without declaring it. FatalData, on the other hand, extends RuntimeException, so it's unchecked and needs no declaration.
A is correct because adding throws DataProblem covers BadData through polymorphism — since BadData is a subclass of DataProblem, declaring the parent satisfies the compiler's requirement. This is the minimal, sufficient fix.
B is wrong because it addresses the wrong exception. FatalData is already unchecked and causes no compile error. Adding throws FatalData doesn't resolve the undeclared checked exception BadData, so the code still won't compile.
C is wrong because catching FatalData inside validate does nothing to address the unchecked FatalData (which didn't need handling anyway) and completely ignores the actual problem — the undeclared checked exception BadData.
D is wrong because "explicitly thrown" doesn't exempt a checked exception from the declare-or-catch rule. The compiler doesn't care that you wrote throw new BadData() clearly; it still requires a throws declaration.
Study tip: Always ask yourself two questions about any thrown exception — "Is it checked?" and "Is it declared or caught?" If both answers aren't satisfied, it won't compile.
- What is the result of compiling this method?
Answer: It fails because the try body cannot throw the checked IOException.
When you see a question mixing try-catch blocks with exception types, your first instinct should be to ask: *can the code in the try block actually throw that exception?* Java enforces this strictly for checked exceptions.
IOException is a checked exception — it must be either thrown explicitly or declared. The compiler knows that Integer.parseInt() can only throw NumberFormatException, which is an unchecked (runtime) exception. Since nothing inside the try block has any possibility of throwing IOException, the compiler rejects the catch clause entirely. This is Java's "unreachable catch block" rule: catching a checked exception that the guarded code provably cannot throw is a compile-time error.
A is wrong because the code never compiles in the first place — the IOException handler isn't just ineffective, it's illegal. B is similarly wrong; it assumes the code compiles but the exception bypasses the handler. While it's true a NumberFormatException wouldn't be caught by an IOException handler, the code never reaches runtime at all. D is a distractor that misapplies the "declare or catch" rule — that rule applies to checked exceptions thrown inside a method, not to unchecked ones like NumberFormatException, so no throws declaration is needed for it.
The correct answer is C: compilation fails because the try body cannot throw IOException.
Study tip: Remember the asymmetry — Java lets you catch unchecked exceptions without complaint, but catching a checked exception that cannot be thrown is a compile error. Always verify whether an exception is checked or unchecked when analyzing try-catch blocks.
- The code does not compile. Which single change makes it compile while leaving the declaration of
Task unchanged? Answer: Catch IOException inside the lambda body and handle it there.
Whenever you see a lambda assigned to a functional interface, remember this rule: the lambda must conform exactly to the interface's method signature — including checked exceptions. The Task.run() method declares no checked exceptions, which means any lambda assigned to Task cannot throw a checked exception either.
Here, readData() throws IOException, a checked exception. When you write () -> readData() inside create(), the compiler sees that the lambda body can throw IOException, but Task.run() doesn't permit it. This is a compile error — the lambda doesn't fit the interface contract.
Option C is the correct fix: catching IOException inside the lambda body makes the exception handled rather than propagated. Since the exception never escapes the lambda, the signature of the lambda matches Task.run() perfectly, and everything compiles.
Option A is a common trap. Adding throws IOException to create() describes what create() itself might throw — but the lambda is assigned to Task, and Task.run() still doesn't allow IOException. The method signature of the enclosing method is irrelevant to what the lambda can throw.
Option B targets call sites of create(), not the actual source of the compile error. The problem occurs when the lambda is defined, not when create() is called.
Option D is a red herring. Explicit casting doesn't change the fact that the lambda body throws a checked exception that Task.run() doesn't declare — the type mismatch still exists.
The key study takeaway: a lambda's ability to throw checked exceptions is governed entirely by its target functional interface, not by the surrounding method context.
- Which statement correctly describes this code?
Answer: It fails because the RuntimeException handler is unreachable after Exception.
When you see multiple catch blocks in Java, think about the hierarchy of exception types. The compiler enforces a rule: no catch block can be unreachable, and a catch block becomes unreachable when a previous block already handles every possible exception that could reach it.
Here's the problem in the code: Exception is the parent class of RuntimeException, which is itself the parent of IllegalArgumentException. When you place catch (Exception ex) first, it captures every exception — checked or unchecked — that could possibly flow through. The catch (RuntimeException ex) block that follows can never be reached because Exception already swallows anything RuntimeException would have caught. The Java compiler detects this and refuses to compile the code, making B correct.
Looking at the wrong answers: A is incorrect because the code never reaches runtime at all — the compiler rejects it before execution. C is a tempting distractor if you confuse checked and unchecked exceptions. IllegalArgumentException is unchecked (it extends RuntimeException), so methods are never required to declare it in a throws clause — no compile error there. D is simply false; Exception absolutely can catch unchecked exceptions. The root Throwable hierarchy means Exception sits above both checked exceptions and RuntimeException, so it catches everything beneath it.
The study tip here: whenever you see multiple catch blocks, mentally order the exception classes from most specific to most general. If a broader type appears before a narrower subtype, the compiler will flag the subtype's block as unreachable. Always catch subclasses first, superclasses last.
- Why does
display fail to compile? Answer: The call is checked against Store.get, which declares the checked IOException.
When you call a method through an interface reference, the Java compiler checks the declared throws clause of the interface method, not the overriding implementation. This is the core concept being tested here.
In display, store is declared as type Store, so store.get() is resolved against Store.get(), which declares throws IOException — a checked exception. Because IOException is checked, the compiler requires you to either catch it or declare it in display's own signature. Since display does neither, it fails to compile. This is why A is correct: the call site is governed by the interface's contract, regardless of what the concrete implementation actually does at runtime.
B is wrong because implementations are allowed to narrow or remove checked exceptions — MemoryStore.get() legally omits throws IOException, and that's perfectly valid Java. No rule forces every override to redeclare the same exceptions.
C is wrong because returning a value without throwing an exception doesn't violate anything. An interface declaring throws IOException is merely permitting the exception, not requiring it. Overrides can be more restrictive.
D is wrong because IOException is a checked exception (it extends Exception, not RuntimeException), so the compiler never treats it as unchecked. The premise of this choice is factually incorrect.
Study tip: Always remember — at a call site, the compiler reads the static type of the reference, not the runtime type. If an interface method declares a checked exception, callers must handle it even if every known implementation never actually throws it.
- What happens when this program is compiled and run?
Answer: It compiles, and calling fail throws an unchecked NullPointerException.
When you see throw null in Java, think carefully about what the JVM actually does at runtime versus what the compiler checks at compile time.
The compiler treats null as a valid value for any reference type, including Throwable and its subclasses. Since throw requires a reference type expression, and null satisfies that requirement syntactically, the code compiles without error. The compiler also does not require a throws declaration because a NullPointerException is an unchecked exception — and that's exactly what happens at runtime. When the JVM attempts to throw null, it cannot process a null reference as an actual exception object, so it automatically substitutes a fresh NullPointerException. This makes C the correct answer.
A is wrong because the compiler does not verify that null refers to a real Throwable instance — it only checks the static type, and null is assignable to any reference type. B is wrong for a similar reason: NullPointerException is a subclass of RuntimeException, which is unchecked, so no throws clause is required in the method signature. D is wrong because the method definitely does not complete normally — the throw statement guarantees an abrupt termination, and the runtime NullPointerException propagates up the call stack.
A useful rule to remember: the compiler performs static type checks, but null bypasses value-level validation. At runtime, throwing null is treated as a programming error, and the JVM rescues the situation by raising a NullPointerException. Whenever you see throw null, expect a runtime NPE, not a compile-time failure.
- Which statement best describes
execute? Answer: It compiles and ultimately throws the unchecked IllegalStateException.
When a try block and a finally block both throw exceptions, Java has a strict rule: the finally block's exception always wins. The original exception from try is silently discarded — a behavior that surprises many developers.
In execute(), the try block throws a checked IOException. Normally, that would require the method to either catch it or declare throws IOException. However, the finally block immediately throws an IllegalStateException before the IOException can propagate. Since IllegalStateException is unchecked, it requires no declaration. From the compiler's perspective, what ultimately escapes the method is only the IllegalStateException — so no throws clause is needed, and the code compiles cleanly. This confirms B as correct.
A is wrong because it assumes the IOException is what the method ultimately throws. The compiler is smart enough to recognize that the finally block unconditionally throws its own exception, meaning the IOException never actually propagates out of execute. No throws IOException declaration is required.
C is wrong for the same reason — the IOException from try is swallowed. At runtime, the IllegalStateException from finally is what the caller receives, not the IOException.
D is a complete fabrication. Java's finally blocks are absolutely permitted to throw exceptions — it's simply a risky pattern because doing so suppresses any exception from the try block.
As a study tip, remember this rule: **finally always gets the last word.** If finally throws, the try's exception vanishes. This is a classic Java gotcha and a frequent exam trap.