What is the difference between throw and throws in Java, and how does the compiler use each one?
They look almost identical and do completely different jobs. throw is a statement that actually raises an exception — it creates an exception object and hands it to the runtime. throws is part of a method signature that declares which checked exceptions the method might raise, so the compiler knows what its callers must deal with.
A method can contain many throw statements and exactly one throws clause. A throws clause may name several exception types separated by commas, and each one is a promise to the caller: you will not see any of these unless the caller handles them or declares them too.
import java.io.IOException;
public class Main {
public static void main(String[] args) {
try {
process(-1);
} catch (IllegalArgumentException e) {
System.out.println("caught: " + e.getMessage());
}
try {
read();
} catch (IOException e) {
System.out.println("caught: " + e.getClass().getSimpleName());
}
}
// throws declares; throw raises.
static void process(int value) {
if (value < 0) {
throw new IllegalArgumentException("value must not be negative: " + value);
}
System.out.println("value ok: " + value);
}
static void read() throws IOException {
throw new IOException("cannot read");
}
}The output shows the distinction in practice. The process method has no throws clause at all, because IllegalArgumentException is unchecked and needs no declaration — the throw statement is enough. The read method declares IOException, so the caller had to catch it or the code would not compile, and the throw statement inside is what actually produces it.
Two things people often get wrong. First, a throws clause does not create an exception; it only advertises one. A method can declare a checked exception it never actually throws, and the compiler will not complain — but it will make every caller handle a failure that may never happen, so the declaration should be honest. Second, throwing a checked exception that is not declared is a compile error, because the compiler believes your method can only throw what it says it can, or an unchecked exception.