Why does the compiler allow throws when the method will never throw the Exception

The throws clause is part of the method's contract. It requires the caller of the method to behave as if the specified exception may be thrown by the method (i.e. either catch the exception or declare their own throws clause).

It's possible that the initial version of a method does not throw the exception specified in the throws clause, but a future version can throw it without breaking the API (i.e. any existing code that calls the method will still pass compilation).

The opposite it also possible. If the method used to throw the exception specified in the throws clause, but a future version of it doesn't throw it anymore, you should keep the throws clause in order not to break existing code that uses your method.

First example: Suppose you have this code which uses methodB:


private static void methodA() {
    methodB(); // doesn't have throws IOException clause yet
}

If later you want to change methodB to throw IOException, methodA will stop passing compilation.

Second example: Suppose you have this code which uses methodB:

private static void methodA() {
    try {
        methodB(); // throws IOException
    }
    catch (IOException ex) {

    }
}

If you remove the throws clause from a future version of methodB, methodA won't pass compilation anymore.

This example is not very interesting when methodA is private, because it can only be used locally (within the same class, where it's easy to modify all the methods that call it).

However, if it becomes public, you don't know who uses (or will use) your method, so you have no control of all the code that may break as a result of adding or removing the throws clause.

And if it's an instance method, there's another reason for allowing the throws clause even if you don't throw the exception - the method can be overridden, and the overriding method may throw the exception even if the base class implementation does not.