The <code>throw</code> Statement in Java
throw raises an exception. Execution of the current method stops and the exception propagates up the call stack until a matching catch handles it or the thread terminates.
Basic
public void setAge(int age) {
if (age < 0) {
throw new IllegalArgumentException("age must be >= 0, got " + age);
}
this.age = age;
}
Throwing a checked exception β must be declared
public void read(Path p) throws IOException { // declaration required
if (!Files.exists(p)) {
throw new IOException("missing: " + p);
}
...
}
Chaining β always include the cause
try {
parse(json);
} catch (ParseException e) {
throw new InvalidRequestException("bad payload", e); // preserve the stack
}
Always use the two-argument constructor when wrapping. Without the cause, the original stack trace is lost and debugging becomes painful.
Re-throw after a catch
try {
risky();
} catch (IOException e) {
log.error("transient IO", e);
throw e; // re-throw, same exception
}
Precise re-throw (Java 7+)
public void doWork() throws IOException, SQLException {
try {
...
} catch (Exception e) { // broad catch
audit(e);
throw e; // compiler infers: only IOException or SQLException
}
}
Since Java 7 the compiler tracks the actual checked types thrown inside the try block, so you don't need throws Exception on the method just because you catch Exception.
Common mistakes
- Wrapping without the cause β
throw new X("failed")loses the stack. Usenew X("failed", e). - Throwing
Exceptionβ forces callers into broad catches. Throw specific types. - Throwing
ThrowableorErrorβ reserved for JVM problems. UseRuntimeExceptionfor programming errors. - Throwing inside a
finallyβ silently replaces any exception from thetryblock.
Related
Pillar: Java exceptions. Siblings: throws clause, custom exceptions.