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

Psy*_*yAp 18 java checked-exceptions

I am wondering why the java compiler allows throws in the method declaration when the method will never throw the Exception. Because "throws" is a way of handling the exception (telling the caller to handle it).

Since there are two ways of handling exception (throws & try/catch). In a try/catch, it doesn't allow the catch of an exception not thrown in the try block but it allows a throws in a method that does may not throw the exception.

private static void methodA() {
    try {
        // Do something
        // No IO operation here
    } catch (IOException ex) {  //This line does not compile because
                              //exception is never thrown from try
        // Handle   
    }
}

private static void methodB() throws IOException { //Why does this //compile when excetion is never thrown in function body
    //Do Something 
    //No IO operation
}
Run Code Online (Sandbox Code Playgroud)

Era*_*ran 25

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
}
Run Code Online (Sandbox Code Playgroud)

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) {

    }
}
Run Code Online (Sandbox Code Playgroud)

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.

而且,如果它是一个实例方法,那么throws即使您不引发异常,也有允许该子句的另一个原因-该方法可以被覆盖,并且即使基类实现不这样做,该覆盖方法也可能引发异常。

  • 关于替代的最后一点应给予更多的重视,恕我直言。“如果函数改变了怎么办”的概念比“即使父函数没有理由抛出特定的异常,即使子函数的当前版本也可能需要这样做”的概念不那么具体。 (2认同)

JB *_*zet 8

因为签名定义了方法的约定。即使该方法现在不抛出IOException,也许将来也会发生,并且您想为此做准备。

假设您现在只为该方法提供一个虚拟实现,但是您知道以后,实际实现可能会抛出IOException。如果编译器阻止您添加此throws子句,则在您提供该方法的实际实现后,将被迫对该方法进行所有调用(递归)。