What is the difference between checked and unchecked exceptions?
Checked exceptions (
Exceptionsubclasses outsideRuntimeException, likeIOException) must be caught or declared withthrows. Unchecked ones (RuntimeExceptionsubclasses likeNullPointerException, plusError) need neither.Checked usually means a condition the caller can recover from, unchecked a bug. An
Errorsuch asOutOfMemoryErrorshould normally not be caught. More in the exceptions guide.What is the difference between
throwandthrows?throwthrows one exception object;throwsin a signature declares what a method may pass up, and is required only for checked exceptions.Javapublic class Main { static int parseAge(String s) throws NumberFormatException { // declares int age = Integer.parseInt(s); if (age < 0) { throw new IllegalArgumentException("age < 0: " + age); // throws } return age; } public static void main(String[] args) { for (String input : new String[] {"30", "-4", "abc"}) { try { System.out.println("ok " + parseAge(input)); } catch (IllegalArgumentException e) { System.out.println(e.getClass().getSimpleName() + ": " + e.getMessage()); } } } }It prints
ok 30,IllegalArgumentException: age < 0: -4andNumberFormatException: For input string: "abc". Onecatchhandles both becauseNumberFormatExceptionextendsIllegalArgumentException.Does
finallyrun when thetryblock returns?Javapublic class Main { static int f() { try { return 1; } finally { System.out.print("finally "); } } public static void main(String[] args) { System.out.println(f()); } }It prints
finally 1.return 1computes its value,finallyruns, and then the method returns.Follow-up: does
finallyalways run? Not if the JVM stops inside thetry, as withSystem.exit(), a crash, or a daemon thread at shutdown.What happens with a
returnin bothtryandfinally?Javapublic class Main { static int f() { try { return 1; } finally { return 2; } } public static void main(String[] args) { System.out.println(f()); } }It prints
2. Areturninfinallyreplaces thetry's return value and would also swallow an exception from thetry, so linters flag it. Usefinallyonly for cleanup.What is try-with-resources and in what order are resources closed?
Resources declared in
try (...)are closed automatically when the block ends, in reverse order and before anycatchruns; anythingAutoCloseableworks.Javaclass Res implements AutoCloseable { private final String name; Res(String name) { this.name = name; System.out.println("open " + name); } @Override public void close() { System.out.println("close " + name); } } public class Main { public static void main(String[] args) { try (Res a = new Res("A"); Res b = new Res("B")) { System.out.println("body"); throw new IllegalStateException("boom"); } catch (IllegalStateException e) { System.out.println("caught " + e.getMessage()); } } }It prints
open A,open B,body,close B,close A,caught boom. An exception thrown byclose()is attached to the main one as suppressed (e.getSuppressed()) instead of replacing it.How do you create a custom exception in Java?
Extend
Exception(checked) orRuntimeException(unchecked) and pass the message tosuper.Javaclass InsufficientFundsException extends RuntimeException { InsufficientFundsException(int balance, int amount) { super("balance " + balance + ", tried to withdraw " + amount); } } public class Main { static int balance = 500; static void withdraw(int amount) { if (amount > balance) throw new InsufficientFundsException(balance, amount); balance -= amount; } public static void main(String[] args) { try { withdraw(200); withdraw(400); } catch (InsufficientFundsException e) { System.out.println("Failed: " + e.getMessage()); } } }It prints
Failed: balance 300, tried to withdraw 400. When wrapping another exception, pass it as the cause (super(message, cause)) to keep its stack trace. See try-catch.What causes a NullPointerException and how do you avoid it?
A
NullPointerExceptionis thrown when anullreference is used as an object: a method call, a field read, an array index or unboxing.Prevent it with
Objects.requireNonNullon inputs, empty collections orOptionalinstead ofnullreturns,"yes".equals(input), andmap.getOrDefault. Since Java 15 the message names the null expression by default (local variable names only when compiled with-g; see JEP 358). More in NullPointerException.Can one
catchblock handle several exceptions, and does the order ofcatchblocks matter?Yes to both. Since Java 7 a multi-catch (
catch (A | B e)) handles several unrelated types in one block, andeis implicitly final. Order matters because the first matchingcatchwins: a subclass must come before its superclass, or the compiler rejects the later block with "exception has already been caught".Javaimport java.io.FileNotFoundException; public class Main { static void risky(int n) throws Exception { if (n == 1) throw new FileNotFoundException("config.txt"); if (n == 2) throw new NumberFormatException("abc"); throw new Exception("generic"); } public static void main(String[] args) { for (int n = 1; n <= 3; n++) { try { risky(n); } catch (FileNotFoundException | NumberFormatException e) { // multi-catch System.out.println("specific: " + e.getClass().getSimpleName()); } catch (Exception e) { // the broader type must come last System.out.println("general: " + e.getMessage()); } } } }It prints
specific: FileNotFoundException,specific: NumberFormatExceptionandgeneral: generic. The types in one multi-catch cannot be subclasses of each other either.What is exception chaining in Java, and why wrap a low-level exception?
Exception chaining wraps a caught exception as the cause of a new one, so the caller gets an error in its own terms while the original stack trace survives. Pass the cause to the constructor (
super(message, cause)) or callinitCause.Javaclass ConfigException extends Exception { ConfigException(String message, Throwable cause) { super(message, cause); } } public class Main { static int readPort(String raw) throws ConfigException { try { return Integer.parseInt(raw); } catch (NumberFormatException e) { throw new ConfigException("bad port in config", e); // keep the cause } } public static void main(String[] args) { try { readPort("80a"); } catch (ConfigException e) { System.out.println(e.getMessage()); System.out.println("cause: " + e.getCause()); } } }It prints
bad port in configandcause: java.lang.NumberFormatException: For input string: "80a". An uncaught chained exception prints both traces, the original underCaused by:. The common mistake isthrow new ConfigException(e.getMessage()), which drops the original trace.Can an overriding method throw a broader checked exception than the method it overrides?
No. An overriding method may declare the same checked exceptions, narrower ones, or none, but not new or broader checked ones. Unchecked exceptions are not restricted. The reason is substitution: code holding a
Readerreference handles only whatReader.read()declares.import java.io.FileNotFoundException; import java.io.IOException; class Reader { void read() throws IOException { } } class LocalReader extends Reader { @Override void read() throws FileNotFoundException { } // OK: narrower } class NetReader extends Reader { @Override void read() throws Exception { } // compile error: broader }javacrejectsNetReaderwith "overridden method does not throw Exception". The same rule applies to a class implementing an interface method.
Java Exception Handling Interview Questions
Checked versus unchecked exceptions, finally, try-with-resources and custom exceptions.