Exceptions ·
‹ Previous Next ›
⏱ 5 min read Modified: 2026-10-30

throw and throws in Java: Difference and Examples

One letter changes the meaning: throw throws an exception, while throws only warns that a method may pass one on. Remove throws IllegalAccessException from a method that contains throw new IllegalAccessException("demo") and the code stops compiling: error: unreported exception IllegalAccessException; must be caught or declared to be thrown.

throw in Java is a statement that throws one specific exception object (an instance of Throwable or its subclass) and interrupts the normal flow of execution: control jumps to the nearest matching catch block. throws is a part of a method or constructor declaration that lists the exception types the method may pass to its caller; for checked exceptions this declaration is mandatory.

Difference between throw and throws

throw is an executable statement in a method body: it throws an exception right at the moment it runs. throws is a declaration in a method signature: it throws nothing by itself, but tells the compiler and the callers which exceptions the method may let out. In practice they work as a pair: throw inside the method, throws in its header.

Criterion throw throws
What it is A statement A part of a method or constructor declaration
Where it is written In the method body, in any block In the signature, after the parameter list
What follows it One object: throw new IOException("...") One or more class names separated by commas: throws IOException, ParseException
What it does Throws the exception and interrupts execution Executes nothing: only declares that the exception may leave the method
When it is required When your code itself has to report an error When a checked exception is not caught inside the method

Both keywords in one method:

public void readConfig() throws IOException {          // throws: declaration
    throw new IOException("File config.txt not found"); // throw: the actual throw
}

The throw statement and throw new: how to throw an exception

To throw an exception in Java, use the throw statement followed by an object of type Throwable. Most often the object is created on the spot with new: throw new IllegalArgumentException("message"). After the throw, the rest of the block is skipped, and the JVM looks for a matching catch in the current method and then up the call stack.

General form:

throw throwableInstance;

throwableInstance must be an object of the Throwable class or of its subclass. You can get such an object in two ways: create it with new, or take the parameter of a catch block (see Rethrowing an exception).

In this example the method validates its argument and reports the error itself with throw new.

public class ThrowNewExample {
    static int divide(int a, int b) {
        if (b == 0) {
            throw new IllegalArgumentException("The divisor must not be zero");
        }
        return a / b;
    }

    public static void main(String[] args) {
        System.out.println(divide(10, 2));
        System.out.println(divide(10, 0));
    }
}

Output:

5
Exception in thread "main" java.lang.IllegalArgumentException: The divisor must not be zero
    at ThrowNewExample.divide(ThrowNewExample.java:4)
    at ThrowNewExample.main(ThrowNewExample.java:11)

IllegalArgumentException is an unchecked exception, so divide() does not need throws. Which standard class to pick for throw new:

Exception When to throw it Example
IllegalArgumentException The method received an invalid argument value throw new IllegalArgumentException("Age: " + age)
IllegalStateException The arguments are fine, but the object is in the wrong state throw new IllegalStateException("Connection is already closed")
NullPointerException null was passed where it is not allowed Objects.requireNonNull(name, "name") throws it for you
UnsupportedOperationException The implementation does not support the operation throw new UnsupportedOperationException("Read-only")

If no standard class describes an error of your domain, write your own — see How to Create a Custom Exception in Java.

Good to know

The stack trace is recorded when the exception object is created (the Throwable constructor calls fillInStackTrace()), not when it is thrown. If you create an exception in one method and throw it in another, the trace points to the place of creation. That is why exceptions are usually created right in the throw new statement.

Rethrowing an exception: throw e

You can throw a caught exception again with throw e inside a catch block. This is how Java rethrows an exception when a method must react to the error (write a log entry, undo part of the work) but leave the final decision to the caller. The same object is thrown, with its original message and stack trace.

public class ThrowExample {
    public static void doSomething() {
        try {
            throw new NullPointerException("demo");
        } catch (NullPointerException e) {
            System.out.println("Caught inside doSomething.");
            throw e; // rethrow the exception
        }
    }

    public static void main(String[] args) {
        try {
            doSomething();
        } catch (NullPointerException e) {
            System.out.println("Caught again: " + e);
        }
    }
}

Output:

Caught inside doSomething.
Caught again: java.lang.NullPointerException: demo

To change the exception type, create a new exception and pass the original one as the cause: throw new IllegalStateException("Could not load the order", e). Why the original error disappears without the second argument is explained in Mistakes beginners make with exceptions.

Precise rethrow (Java 7+)

Since Java 7 the compiler analyzes which checked exceptions the try block can really throw. So after catch (Exception e) { throw e; } the method can declare the exact type instead of throws Exception:

import java.io.IOException;

public class PreciseRethrow {
    static void read(boolean fail) throws IOException {
        try {
            if (fail) {
                throw new IOException("No access to the file");
            }
            System.out.println("File read");
        } catch (Exception e) {
            System.out.println("Log: " + e.getMessage());
            throw e; // the compiler knows it can only be an IOException
        }
    }

    public static void main(String[] args) {
        try {
            read(false);
            read(true);
        } catch (IOException e) {
            System.out.println("Handled in main: " + e);
        }
    }
}

Output:

File read
Log: No access to the file
Handled in main: java.io.IOException: No access to the file

The rule works only if the parameter e is not reassigned in the catch block (it is effectively final). Add the line e = new Exception(); and you get error: unreported exception Exception; must be caught or declared to be thrown.

The throws keyword and checked exceptions

The throws keyword is written in a method declaration after the parameter list and lists the exceptions the method does not handle itself. For checked exceptions it is mandatory: if a method can throw one and does not catch it, the code does not compile without throws. For Error, RuntimeException and their subclasses throws is not required.

The idea behind the rule: if a method can cause an exception it does not handle, the calling code has to know about it to protect itself — catch the exception or pass it further. Which classes are checked is covered in Checked vs unchecked exceptions in Java.

An example of the throws keyword:

public class ThrowsGenerateExample {
    public static void throwOne() throws IllegalAccessException {
        System.out.println("Inside throwOne.");
        throw new IllegalAccessException("demo");
    }

    public static void main(String[] args) {
        try {
            throwOne();
        } catch (IllegalAccessException e) {
            System.out.println("Caught " + e);
        }
    }
}

Output:

Inside throwOne.
Caught java.lang.IllegalAccessException: demo

IllegalAccessException extends Exception directly, so it is a checked exception. If you remove throws IllegalAccessException from the signature of throwOne(), the compiler stops at the line with throw:

ThrowsGenerateExample.java:4: error: unreported exception IllegalAccessException; must be caught or declared to be thrown
        throw new IllegalAccessException("demo");
        ^

The same error appears in main if you remove the try-catch around the call to throwOne(): the calling method must either catch the declared exception or declare it in its own throws, for example public static void main(String[] args) throws IllegalAccessException.

Unchecked exceptions can be listed in throws too — it is not an error but documentation for the reader; the compiler will not force callers to handle them. Constructors can declare throws as well. The rules for overriding methods and for subclass constructors are a separate topic (exceptions and inheritance).

A common misconception

throws does not handle an exception; it only shifts the responsibility to the caller. If the exception reaches a main declared with throws Exception, the program still terminates and prints the stack trace — exactly as if nothing had been handled.

Multiple exceptions in throws

You can list any number of exception types in throws, separated by commas, for example void load() throws IOException, ParseException. The order does not matter. The calling code must handle every checked exception from the list: with separate catch blocks, with one multi-catch, or with a common superclass.

import java.io.IOException;
import java.text.ParseException;

public class MultipleThrowsExample {
    static void load(int mode) throws IOException, ParseException {
        if (mode == 1) {
            throw new IOException("File is unavailable");
        }
        if (mode == 2) {
            throw new ParseException("Invalid date", 0);
        }
        System.out.println("Loaded");
    }

    public static void main(String[] args) {
        for (int mode = 0; mode <= 2; mode++) {
            try {
                load(mode);
            } catch (IOException | ParseException e) {
                System.out.println("Error: " + e);
            }
        }
    }
}

Output:

Loaded
Error: java.io.IOException: File is unavailable
Error: java.text.ParseException: Invalid date

Details of the throws list:

  • throws Exception covers all checked exceptions at once, but hides from the caller what can actually go wrong. List specific types instead.
  • A subclass and its superclass together (throws FileNotFoundException, IOException) are allowed, although redundant. In multi-catch such a combination is a compile-time error: see Multi-Catch: Multiple Exceptions in One Catch Block.

What you can and cannot throw

Only an expression of type Throwable or its subclass is allowed after throw. Primitive types such as int or char, strings and any other classes except Throwable and its descendants cannot be thrown — that is a compile-time error. If a reference of a suitable type is null, the code compiles, but at run time a NullPointerException is thrown.

Code Compiles? What happens
throw new IllegalArgumentException("..."); Yes Unchecked exception, throws is not needed
throw new IOException("..."); Only with catch or throws IOException Otherwise unreported exception IOException
throw e; (a catch parameter) Yes Rethrows the same object
throw "Error"; No incompatible types: String cannot be converted to Throwable
throw 42; No incompatible types: int cannot be converted to Throwable
throw null; or a reference equal to null Yes At run time — NullPointerException instead of the exception you intended

What does this code print?

public class ThrowNullExample {
    public static void main(String[] args) {
        RuntimeException ex = null;
        try {
            throw ex;
        } catch (NullPointerException e) {
            System.out.println("Caught: " + e);
        }
    }
}

Output in Java 15 and newer (helpful NullPointerException messages are on by default):

Caught: java.lang.NullPointerException: Cannot throw exception because "<local1>" is null

If the class is compiled with the -g flag, the variable name ex appears instead of <local1>. In Java 8 the message is empty: Caught: java.lang.NullPointerException. A catch (RuntimeException e) block would catch it here too, because NullPointerException is its subclass.

Code after throw is unreachable

The throw statement always completes the current block, so a statement right after it in the same block is unreachable and the compiler reports unreachable statement. For the same reason a method that returns a value may end with throw and no return.

static void stop() {
    throw new IllegalStateException("Stop");
    System.out.println("Never runs"); // error: unreachable statement
}

If throw is inside an if, the code after the if stays reachable: the compiler cannot know in advance whether the condition will be true. Ending a method this way is fine — there is no missing return statement error:

static int parsePositive(String s) {
    int n = Integer.parseInt(s);
    if (n > 0) {
        return n;
    }
    throw new IllegalArgumentException("A positive number is expected: " + s);
}

The call parsePositive("7") returns 7, parsePositive("-3") throws IllegalArgumentException: A positive number is expected: -3, and parsePositive("abc") throws NumberFormatException from Integer.parseInt().

Frequently Asked Questions

Can I use throw without throws?

Yes, in two cases: when the thrown exception is unchecked (RuntimeException, Error and their subclasses), or when a checked exception is caught by a catch block in the same method. If a checked exception leaves the method, throws is required. The rule with an example is in The throws keyword and checked exceptions.

Can I declare an exception in throws that the method never actually throws?

Yes, the compiler does not check this for throws: void run() throws IOException {} compiles. But then every calling method has to handle or declare IOException. With catch it is the opposite: a catch for a checked exception that the try block cannot throw is a compile-time error.

What does throws Exception on the main method mean?

The main method passes checked exceptions to the JVM without handling them. If such an exception occurs, the JVM prints the stack trace and terminates the main thread. This is convenient in tutorials; in production code it is better to handle exceptions or declare specific types.

What is the difference between throws and the @throws Javadoc tag?

throws is part of the code and is checked by the compiler. @throws (a synonym of @exception) is a documentation tag in a /** ... */ comment: it describes when a method throws an exception and is often used for unchecked exceptions, for example @throws IllegalArgumentException if amount is negative. The compiler does not check this tag.

Why can't I throw an IOException inside a forEach lambda?

The accept method of the Consumer functional interface does not declare throws, so a checked exception cannot leave the lambda body — the compiler reports unreported exception IOException. Catch it inside the lambda and, if needed, wrap it in UncheckedIOException or another unchecked exception.

Practice

Reinforce this lesson with hands-on tasks, each with a level and a time estimate.

All module tasks →

Comments

Please log in or register to have a possibility to add comment.