← Home
☕Java Developer Interview Questions — Fresher to 5 YOEJava Dev InterviewNEW
🚨

Exception Handling

Checked vs unchecked, try-with-resources · 15 questions

1

What is the exception class hierarchy in Java (Throwable, Error, Exception, RuntimeException)?

Must Know🌱 Fresher
🌳 Throwable hierarchy
Throwable
  ├── Error                     (JVM-level problems -- don't try to recover)
  │     └── OutOfMemoryError, StackOverflowError, ...
  └── Exception
        ├── RuntimeException     (UNCHECKED -- programming errors)
        │     └── NullPointerException, ArrayIndexOutOfBoundsException,
        │         ClassCastException, IllegalArgumentException, ...
        └── (everything else)    (CHECKED -- must catch or declare)
              └── IOException, SQLException, ...

Error represents serious problems the JVM itself hits (out of memory, stack overflow) that application code generally shouldn't try to catch/recover from. Exception is for conditions application code is expected to handle — split into checked and unchecked (see the next question).

Exceptions
2

What is the difference between checked and unchecked exceptions?

Must Know🌱 Fresher

Checked exceptions (subclasses of Exception but not RuntimeException) must be either caught or declared in the method's throws clause — the compiler enforces it. They model recoverable, expected failure conditions the caller should plan for (a file not existing, a network call failing).

Unchecked exceptions (RuntimeException and its subclasses, plus Error) require no such declaration. They typically represent programming bugs (null dereference, bad array index, invalid cast) — the fix is to correct the code, not to catch and continue.

Exceptions
3

What is the order of execution for try, catch, and finally — especially with a return statement?

Must Know🌱 Fresher

try runs; if an exception occurs, the matching catch runs; then finally always runs — whether the try block completed normally, threw an exception (caught or not), or even hit a return.

finally overriding a return valuejava
static int test() {
    try {
        return 1;
    } finally {
        System.out.println("finally runs before the caller gets a value");
        // if finally itself has a return here, it SILENTLY overrides
        // the try block's return -- a well-known gotcha, avoid returning from finally
    }
}
// test() returns 1, but "finally runs..." prints first

If finally itself contains a return or throw, it silently discards whatever the try/catch was about to return or throw — considered a code smell, and most linters flag it.

Exceptionstry-catch-finally
4

What is try-with-resources, and how does AutoCloseable work?

Must Know🌱 Fresher

Try-with-resources (Java 7) automatically closes any resource that implements AutoCloseable when the block exits — normally or via exception — without a manual finally { resource.close(); }. Multiple resources are closed in reverse declaration order, and if both the try body and the automatic close() throw, the close's exception is suppressed and attached to the original via getSuppressed() rather than replacing it.

try-with-resourcesjava
try (var in = new FileInputStream("a.txt");
     var out = new FileOutputStream("b.txt")) {
    in.transferTo(out);
} // both closed automatically, out first then in (reverse order)
ExceptionsAutoCloseable
5

What is the difference between `throw` and `throws`?

Must Know🌱 Fresher
throwthrows
What it isA statement — actually raises an exception instanceA method-signature clause — declares what a method might raise
Where it appearsInside a method bodyAfter the method's parameter list
CountThrows exactly one exception instanceCan declare multiple exception types, comma-separated
Examplethrow new IllegalStateException();void read() throws IOException { ... }
Exceptions
6

What are the most common unchecked exceptions you run into, and what causes each?

Must Know🌱 Fresher
  • NullPointerException — calling a method or accessing a field on a null reference.
  • ArrayIndexOutOfBoundsException — indexing an array outside [0, length-1].
  • ClassCastException — casting an object to a type it isn't actually an instance of.
  • NumberFormatException — parsing a non-numeric string with Integer.parseInt etc.
  • ArithmeticException — e.g. integer division by zero.
  • IllegalArgumentException / IllegalStateException — a method was called with a bad argument, or an object was in the wrong state for the call.
Exceptions
7

What is a multi-catch block?

Important🌱 Fresher

Java 7 let a single catch clause handle several unrelated exception types with identical handling logic, joined with |, avoiding duplicated catch blocks:

Multi-catchjava
try {
    riskyIO();
} catch (IOException | SQLException e) {
    log.error("operation failed", e);
}

The caught variable is effectively final, and its static type is the most specific common supertype of the listed exceptions — you can't reassign it inside the block.

Exceptions
8

How do you create a custom exception, and should it be checked or unchecked?

Important🌱 Fresher

Extend Exception for a checked custom exception, or RuntimeException for unchecked — and (as best practice) provide constructors that accept a message and a cause, so it can wrap/chain an underlying exception.

Custom exception with a cause constructorjava
public class InsufficientBalanceException extends RuntimeException {
    public InsufficientBalanceException(String message) { super(message); }
    public InsufficientBalanceException(String message, Throwable cause) { super(message, cause); }
}

Prefer unchecked for most business-logic errors in modern codebases (checked exceptions tend to force ugly boilerplate up call chains, especially through lambdas/streams which can't declare checked exceptions at all) — reserve checked exceptions for cases where you specifically want to force callers to consciously decide how to recover.

Exceptions
9

What is exception chaining, and why does it matter?

Important📊 Mid

Exception chaining preserves the original exception as the "cause" of a new one you throw in its place — usually done when you catch a low-level exception and want to re-throw a higher-level, more meaningful one without losing the original stack trace/root cause.

Chaining via causejava
try {
    parseConfig(file);
} catch (IOException e) {
    throw new ConfigLoadException("could not load config: " + file, e); // e becomes the cause
}
// later: exception.getCause() returns the original IOException
// and printStackTrace() shows both traces: "...Caused by: IOException..."

Without chaining (just throwing a fresh exception with a new message and no cause), you lose the original stack trace entirely — a common debugging pain point in poorly written code.

Exceptions
10

What is the difference between the finally block, the finalize() method, and close()?

Important📊 Mid
finallyfinalize()close()
What it isA block, part of try/catch syntaxA method on Object, called by the GC before reclaiming an objectA method on AutoCloseable/Closeable, called by you (or try-with-resources)
TimingDeterministic — right after try/catchNon-deterministic — whenever (if ever) GC decides to collect the objectDeterministic — whenever you call it
StatusStandard cleanup mechanismDeprecated since Java 9 — unreliable, has performance costsStandard resource-cleanup mechanism
ExceptionsGC
11

Are there cases where the finally block does NOT execute?

Important📊 Mid
  • The JVM itself is killed — System.exit(), Runtime.halt(), or the process being killed (OS kill -9, power loss).
  • The thread running the try block is forcibly stopped/killed (deprecated Thread.stop()).
  • An infinite loop or a permanent block (e.g. waiting on a lock that's never released) in the try block itself — finally just never gets a turn to run.
  • A StackOverflowError or fatal Error so severe the JVM can't unwind the stack cleanly.
Exceptions
12

Can an overriding method throw broader checked exceptions than the method it overrides?

Important📊 Mid

No. An overriding method can throw the same checked exceptions as the parent, narrower/fewer ones, or none at all — but never a new or broader checked exception. This preserves the Liskov substitution principle: any code calling the method through the parent's declared type must still compile without needing to catch exceptions the parent never advertised.

Legal vs illegal narrowingjava
class Parent { void read() throws IOException { } }

class ChildOk extends Parent {
    void read() throws FileNotFoundException { } // OK -- FileNotFoundException is narrower than IOException
}
class ChildBad extends Parent {
    void read() throws Exception { } // COMPILE ERROR -- broader than IOException
}

Unchecked exceptions have no such restriction — an override can throw any RuntimeException regardless of what the parent declared, since callers were never forced to handle those anyway.

ExceptionsOOP
13

Why are exceptions considered expensive, and why shouldn’t they be used for normal control flow?

Advanced📊 Mid

Constructing an exception captures a full stack trace at the moment of creation (fillInStackTrace()), walking every frame on the call stack — that's real work, done even if the exception is never actually logged or shown to anyone. Throwing also unwinds the stack, which bypasses normal method-return optimizations the JIT would otherwise apply. Using exceptions for expected, frequent outcomes (e.g. "not found" on a hot path, or using exceptions to break out of a loop instead of a break) turns a cheap conditional into comparatively expensive stack-trace capture on every call — prefer return values (Optional, a result/sentinel, a boolean) for outcomes that are a normal part of control flow, and reserve exceptions for genuinely exceptional, rare conditions.

ExceptionsPerformance
14

Why shouldn’t you catch Throwable or Error?

Advanced📊 Mid

Catching Throwable (or Error) also swallows JVM-fatal conditions like OutOfMemoryError and StackOverflowError — problems the application generally cannot safely recover from. Silently catching and continuing after an OutOfMemoryError, for instance, can leave the application in a corrupted, half-functioning state that's far harder to debug than simply letting the JVM/process die and restart cleanly. As a rule, catch specific Exception subtypes you actually know how to handle; let unrecoverable Errors propagate.

Exceptions
15

When should you use Optional instead of throwing an exception for a "not found" case?

Optional📊 Mid

Use Optional<T> when "not found" / "no value" is a normal, expected outcome the caller should explicitly handle inline (e.g. findById in a repository — not finding a row is routine). Use an exception when the missing value represents a genuine error condition the caller likely can't reasonably continue past without addressing (e.g. a required configuration value being absent at startup). A common mistake is overusing Optional for method parameters or fields — it's meant primarily as a return type for "value or nothing" results, not a general-purpose null replacement everywhere.

ExceptionsOptionalJava 8