00:00

throws Keyword in Java – Explained with Examples

The throws keyword appears in a method declaration and lists the checked exceptions the method may throw instead of handling itself. It is a promise to callers: "this method can fail in these ways, so be ready." The compiler then makes sure every caller either catches those exceptions or declares them in turn.

This tutorial explains when throws is required, how exceptions are passed up the call chain, how to declare several exceptions, and the rules for overriding methods.

1. Syntax

throws syntax
returnType methodName(parameters) throws ExceptionType1, ExceptionType2 {
    // ...
}

String readConfig(Path path) throws IOException { ... }

2. Why throws Is Needed

Java's catch-or-declare rule says that code that can throw a checked exception must either catch it or declare it. If you do neither, the code does not compile:

javac output
Bad.java:2: error: unreported exception IOException; must be caught or declared to be thrown
public class Bad { static String r() { return Files.readString(Path.of("x")); } }
                                                              ^
1 error

Adding throws IOException to the method declares the exception and moves the responsibility for handling it to the caller:

ThrowsBasics.java
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;

public class ThrowsBasics {
    // This method does not handle IOException itself: it declares it
    static String readConfig(Path path) throws IOException {
        return Files.readString(path);
    }

    public static void main(String[] args) {
        try {
            System.out.println(readConfig(Path.of("missing-config.properties")));
        } catch (IOException e) {                         // the caller handles it
            System.out.println("Config not loaded: " + e.getClass().getSimpleName() + " - " + e.getMessage());
        }
    }
}
Output
Config not loaded: NoSuchFileException - missing-config.properties

NoSuchFileException is a subclass of IOException, so declaring and catching IOException covers it.

3. Passing Exceptions Up the Call Chain

A method that calls a throws method can also declare the exception, passing it further up. The exception is finally handled by the method that knows what to do about it:

PassingUp.java
public class PassingUp {
    static class StockException extends Exception {
        StockException(String message) { super(message); }
    }

    static void reserve(String item, int qty) throws StockException {
        if (qty > 5) throw new StockException("Only 5 " + item + "s in stock");
        System.out.println("Reserved " + qty + " " + item + "(s)");
    }

    static void placeOrder(String item, int qty) throws StockException {   // passes it up again
        System.out.println("Placing order for " + item);
        reserve(item, qty);
        System.out.println("Order placed");
    }

    public static void main(String[] args) {
        try {
            placeOrder("lamp", 2);
            placeOrder("chair", 9);
        } catch (StockException e) {
            System.out.println("Order failed: " + e.getMessage());
        }
    }
}
Output
Placing order for lamp
Reserved 2 lamp(s)
Order placed
Placing order for chair
Order failed: Only 5 chairs in stock

"Order placed" was not printed for the chair: when reserve() threw, both reserve() and placeOrder() ended immediately, and main() handled the problem.

4. Declaring Several Exceptions

List several exception types separated by commas. Callers can catch them separately or together:

MultipleThrows.java
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;

public class MultipleThrows {
    // A method can declare several exceptions, separated by commas
    static String fetch(String address) throws URISyntaxException, IOException {
        URI uri = new URI(address);
        if (uri.getHost() == null) throw new IOException("No host in " + address);
        return "content of " + uri.getHost();
    }

    public static void main(String[] args) {
        for (String a : new String[] {"https://example.com/page", "not a uri", "file:///tmp/x"}) {
            try {
                System.out.println(fetch(a));
            } catch (URISyntaxException e) {
                System.out.println("Bad address: " + e.getMessage());
            } catch (IOException e) {
                System.out.println("Fetch failed: " + e.getMessage());
            }
        }
    }
}
Output
content of example.com
Bad address: Illegal character in path at index 3: not a uri
Fetch failed: No host in file:///tmp/x

5. throws and Unchecked Exceptions

Declaring unchecked exceptions (RuntimeException subclasses) is allowed but not required, and the compiler does not force callers to handle them. Some APIs declare them anyway as documentation, but the usual way to document unchecked exceptions is the Javadoc @throws tag.

6. throws and Method Overriding

An overriding method may throw fewer or narrower checked exceptions than the method it overrides, but never new or broader ones. Otherwise code written against the parent type would receive exceptions it was never told about:

OverridingRules.java
import java.io.FileNotFoundException;
import java.io.IOException;

public class OverridingRules {
    static class Reader {
        String read() throws IOException { return "base"; }
    }

    static class FileBasedReader extends Reader {
        @Override
        String read() throws FileNotFoundException {   // narrower checked exception: allowed
            return "file";
        }
    }

    static class MemoryReader extends Reader {
        @Override
        String read() {                                 // no exception at all: allowed
            return "memory";
        }
        // String read() throws Exception { ... }      // broader exception: compile error
    }

    public static void main(String[] args) throws IOException {
        Reader[] readers = {new Reader(), new FileBasedReader(), new MemoryReader()};
        for (Reader r : readers) System.out.println(r.read());
    }
}
Output
base
file
memory
Overriding method declares…Allowed?
The same checked exceptionYes
A subclass of it (narrower)Yes
No exceptionYes
Any unchecked exceptionYes
A broader checked exception (e.g. Exception)No
An unrelated new checked exceptionNo

7. Declaring throws on main

public static void main(String[] args) throws Exception compiles, and any exception then ends the program with a stack trace. It is acceptable for small demos and scripts, but real applications should handle exceptions and report them clearly.

8. Best Practices

  • Declare specific exception types, not throws Exception.
  • Declare an exception only if callers can reasonably respond to it; otherwise handle it or wrap it.
  • At layer boundaries, translate low-level exceptions (such as SQLException) into exceptions that fit the layer.
  • Document each declared exception with a Javadoc @throws tag explaining when it occurs.

9. Summary

  • throws in a method declaration lists exceptions the method may throw.
  • It is required for checked exceptions that are not caught inside the method.
  • Callers must catch the declared checked exceptions or declare them too.
  • Several exceptions can be declared, separated by commas.
  • Overriding methods may declare fewer or narrower checked exceptions, never broader ones.

Related Tutorials