throw vs throws in Java with Examples
Introduction
So far we have caught exceptions thrown by the Java library. Your own code can throw exceptions too - to reject an invalid argument, or to report that an operation failed. Java has two keywords for this which look almost the same but do completely different jobs: throw and throws. This tutorial explains throw vs throws in Java with examples. We will start with the
(Note - This tutorial builds on Checked vs Unchecked ExceptionsClick to read tutorial: Checked vs Unchecked Exceptions in Java and try, catch, finally and multi-catchClick to read tutorial: Java try, catch, finally and Multi-catch with Examples.) throw - throwing an exception
Where,
OUTPUT of the above code
Explanation of the code
throws - declaring exceptions
Where,
OUTPUT of the above code
Explanation of the code
OUTPUT of the above code
The caller sees an exception which describes the problem in its own terms - an invalid order quantity - while the original
throw vs throws - comparison
A memory aid: throw is an action, done once; throws is a warning label on the method. throws and method overriding When a subclass overrides a method, its
OUTPUT on compiling the above code
Declaring
throw statement, and use it to validate arguments. We will then declare exceptions with the throws clause, and see how a declared exception travels up to its callers. Next we will rethrow and wrap exceptions while keeping the original cause. Lastly, we will compare the two keywords side by side, and look at the rules for throws when methods are overridden.(Note - This tutorial builds on Checked vs Unchecked ExceptionsClick to read tutorial: Checked vs Unchecked Exceptions in Java and try, catch, finally and multi-catchClick to read tutorial: Java try, catch, finally and Multi-catch with Examples.) throw - throwing an exception
throw is a statement which throws one exception object, right now.throw new ExceptionType("message");- the expression after
throwmust be an object ofThrowableor a subclass - almost always a newly created exception. - the method stops immediately, like a
return, and the exception travels up the call stack until acatchblock handles it. - the message should explain what went wrong, including the bad value, so that whoever reads it can fix the problem.
IllegalArgumentException - or a more specific exception - when they are invalid. Failing early with a clear message is much better than carrying on with bad data and failing confusingly later.
Validating arguments with throw
//ThrowDemo.java
public class ThrowDemo {
static double withdraw(double balance, double amount) {
if (amount <= 0) {
throw new IllegalArgumentException("Amount must be positive, but was " + amount);
}
if (amount > balance) {
throw new IllegalStateException("Insufficient funds: balance " + balance + ", requested " + amount);
}
return balance - amount;
}
public static void main(String[] args) {
System.out.println("New balance: " + withdraw(500, 120));
double[] requests = {-20, 800};
for (double amount : requests) {
try {
withdraw(500, amount);
} catch (IllegalArgumentException | IllegalStateException e) {
System.out.println(e.getClass().getSimpleName() + ": " + e.getMessage());
}
}
String name = null;
String checked = java.util.Objects.requireNonNull(name, "name must not be null");
}
}
New balance: 380.0 IllegalArgumentException: Amount must be positive, but was -20.0 IllegalStateException: Insufficient funds: balance 500.0, requested 800.0 Exception in thread "main" java.lang.NullPointerException: name must not be null at java.base/java.util.Objects.requireNonNull(Objects.java:246) at ThrowDemo.main(ThrowDemo.java:24)
- Each
throwstoppedwithdraw()at once, so no balance was returned for the invalid requests. IllegalArgumentExceptionmeans "you passed a bad value", andIllegalStateExceptionmeans "this cannot be done right now". Both are unchecked, sowithdraw()does not need to declare them.Objects.requireNonNull()is a ready-made check which throws aNullPointerExceptionwith your message when its argument isnull. It was not caught, so the program ended with a stack trace.
throws is part of a method declaration. It lists the checked exceptions the method may throw but does not handle itself, so that its callers know to deal with them.returnType methodName(parameters) throws ExceptionType1, ExceptionType2 { ... }- several exception types can be listed, separated by commas.
- for checked exceptions,
throwsis how a method satisfies the compiler's catch or declare rule. Every caller must then catch or declare them in turn. - unchecked exceptions can be listed too, as documentation, but the compiler ignores them.
Declaring checked exceptions with throws
//ThrowsDemo.java
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
public class ThrowsDemo {
static String readFirstLine(Path file) throws IOException {
if (!Files.exists(file)) {
throw new IOException("No such file: " + file);
}
return Files.readAllLines(file).get(0);
}
static int readPort(Path configFile) throws IOException { // passes the exception on
String line = readFirstLine(configFile);
return Integer.parseInt(line.substring(line.indexOf('=') + 1).trim());
}
public static void main(String[] args) throws IOException {
Path config = Path.of("server.conf");
Files.writeString(config, "port = 8080\n");
System.out.println("Port: " + readPort(config));
try {
readPort(Path.of("missing.conf"));
} catch (IOException e) {
System.out.println("Could not read port: " + e.getMessage());
}
Files.delete(config);
}
}
Port: 8080 Could not read port: No such file: missing.conf
readFirstLine()both throws anIOExceptionwiththrow, and declares it withthrows- the two keywords working together.readPort()does not handle the exception, so it declares it as well, passing it up to its caller. This is called propagating the exception.main()catches it for the missing file.main()also declaresthrows IOException, becausewriteString()anddelete()can throw it - acceptable in a small program, but in real applications exceptions should be handled before they reachmain().
catch block can throw too. Two patterns are common -- Rethrowing: do something with the exception - such as logging it - then
throw e;to pass it on unchanged. - Wrapping: throw a new, more meaningful exception, passing the original as its cause. The cause keeps the original details and stack trace, which are shown as "Caused by:" in the output. Never throw a new exception without the cause - the information about what really went wrong would be lost.
Wrapping a low-level exception with its cause
//WrapDemo.java
public class WrapDemo {
static int parseQuantity(String text) {
try {
return Integer.parseInt(text);
} catch (NumberFormatException e) {
throw new IllegalArgumentException("Invalid order quantity '" + text + "'", e); // e is the cause
}
}
public static void main(String[] args) {
try {
parseQuantity("12x");
} catch (IllegalArgumentException e) {
System.out.println("Message : " + e.getMessage());
System.out.println("Cause : " + e.getCause());
}
parseQuantity("abc");
}
}
Message : Invalid order quantity '12x' Cause : java.lang.NumberFormatException: For input string: "12x" Exception in thread "main" java.lang.IllegalArgumentException: Invalid order quantity 'abc' at WrapDemo.parseQuantity(WrapDemo.java:7) at WrapDemo.main(WrapDemo.java:18) Caused by: java.lang.NumberFormatException: For input string: "abc" at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:67) at java.base/java.lang.Integer.parseInt(Integer.java:564) at java.base/java.lang.Integer.parseInt(Integer.java:661) at WrapDemo.parseQuantity(WrapDemo.java:5) ... 1 more
NumberFormatException is still there, in the "Caused by:" section of the stack trace and through getCause().
| throw | throws | |
| What it is | A statement | A clause in a method (or constructor) declaration |
| What it does | Throws one exception object now | Declares exception types the method may throw |
| Followed by | An exception object: throw new IOException("...") | One or more class names: throws IOException, SQLException |
| Where | Inside a method body | After the parameter list |
| Effect on the compiler | A thrown checked exception must be caught or declared | Satisfies catch-or-declare; makes callers handle the exceptions |
A memory aid: throw is an action, done once; throws is a warning label on the method. throws and method overriding When a subclass overrides a method, its
throws clause may only narrow the checked exceptions of the method it overrides: it can declare the same checked exceptions, subclasses of them, or none at all - but not new or broader checked exceptions. Code written against the parent class only expects the parent's exceptions, so a subclass must not surprise it with others. Unchecked exceptions are not restricted.
An overriding method cannot add a broader checked exception
//OverrideThrows.java
import java.io.FileNotFoundException;
import java.io.IOException;
public class OverrideThrows {
static class Loader {
void load() throws FileNotFoundException { }
}
static class NetworkLoader extends Loader {
@Override
void load() throws IOException { } // IOException is broader than FileNotFoundException
}
}
OverrideThrows.java:12: error: load() in NetworkLoader cannot override load() in Loader
void load() throws IOException { } // IOException is broader than FileNotFoundException
^
overridden method does not throw IOException
1 error
throws FileNotFoundException, or nothing, in NetworkLoader would compile. Overriding itself is covered in the @Override annotation tutorialClick to read tutorial on the @Override annotation.
Summary
In this tutorial we first used the throw statement to throw exceptions, and validated method arguments with IllegalArgumentException, IllegalStateException and Objects.requireNonNull(). We then declared checked exceptions with the throws clause, and propagated an IOException up through two methods. Next we rethrew and wrapped exceptions, keeping the original as the cause. We then compared throw and throws side by side, and lastly saw that an overriding method cannot declare broader checked exceptions. In the next tutorial, we will define our own exception classes with custom exceptionsClick to read tutorial: Creating Custom Exceptions in Java with Examples.Core Java Tutorials
Java try, catch, finally and Multi-catch with ExamplesClick to read tutorial: Java try, catch, finally and Multi-catch with Examples Creating Custom Exceptions in Java with ExamplesClick to read tutorial: Creating Custom Exceptions in Java with Examples Checked vs Unchecked Exceptions in JavaClick to read tutorial: Checked vs Unchecked Exceptions in Java Java try-with-resources and AutoCloseable ExplainedClick to read tutorial: Java try-with-resources and AutoCloseable Explained Java Exception Handling Best PracticesClick to read tutorial: Java Exception Handling Best Practices Java Math Class: Essential Methods with ExamplesClick to read tutorial: Java Math Class: Essential Methods with Examples
Java try, catch, finally and Multi-catch with ExamplesClick to read tutorial: Java try, catch, finally and Multi-catch with Examples Creating Custom Exceptions in Java with ExamplesClick to read tutorial: Creating Custom Exceptions in Java with Examples Checked vs Unchecked Exceptions in JavaClick to read tutorial: Checked vs Unchecked Exceptions in Java Java try-with-resources and AutoCloseable ExplainedClick to read tutorial: Java try-with-resources and AutoCloseable Explained Java Exception Handling Best PracticesClick to read tutorial: Java Exception Handling Best Practices Java Math Class: Essential Methods with ExamplesClick to read tutorial: Java Math Class: Essential Methods with Examples