The Java compiler seems inconsistent if there is some code that clearly can not throw an exception, and you write surrounding code that declares that the code can throw that exception.
Consider these code snippets.
Snippet 1
A catch
of an exception that is never thrown.
public void g(){
try {
} catch (FileNotFoundException e) {//any checked exception
}
}
It is compile error with message
Unreachable catch block for FileNotFoundException. This exception is never thrown from the try statement body
Snippet2
A throws
declaration indicating an exception that is never thrown.
public void g() throws FileNotFoundException{
}
It compiles fine.
Therefore, the results of the first code snippet shows that the compiler can calculate if a method can throw an exception listed in the throws
list. So it seems the compiler is deliberately not reporting an error for the second snippet. But Why? Why does the compiler allow you to write exceptions in throws
section even if it the compiler knows thst those exceptions can not be thrown?
Just a try !!
For second case there might be a possibility that some other class overrides this method in the future and a code is written inside that which can throw this exception.
The compiler allows this because the
throws
clause of the method is part of the signature of the method, rather than part of its implementation. It is possible that the implementation might change at some point, while keeping the signature the same. An old implementation might have thrown a checked exception, but the new one might not. Or the designer of the signature might have wanted to give the implementer the flexibility to throw a checked exception when that is not always necessary.Since you wanted other views -
Consider two implementations of the same signature in two different subclasses.
For example, (a made up example),
Even though the subclass implementation
StudentDBReader
is not throwingIOException
, the parent classStudentLoader
still has to saythrows IOException
because other implementations ofStudentLoader
may throw it. So even though the exception may not be thrown by the method, you have a way of indicating to the caller usingStudentLoader
reference (that points to either of the two subclasses instance) that the caller must handle these exceptions.In your snippet 1 showing method
g()
, there is no scope of inheritance. The code is right there in the try block. If any statement in try is throwing a checked Exception, you will have to handle it. In case of throws clause, scope for inheritance has to be allowed. Compiler cannot decide which version ofreadStudentData( )
will be called at runtime.I would expect that compiler should give an error in case of static methods, if Exception mentioned in throws clause is not thrown, since static methods do not participate in inheritance. I am not sure why throws clause in static methods can contain Exceptions which are never thrown in implementation. It will not be overridden anyway, so why not throw error here? There might be something I am missing.
Above code compiles and runs as explained in @Raedwald answer.
I don't suggest this as an answer, just a place to post the code that I attempted to include in comments.
Throws
does not handle exception, It indicates the throwing exception upwards from where method will be called. In other words it will just pass exception to the caller.While
try...catch
block handles the exception, and that is why Java compiler will check if there is any exception to handle which is being caught incatch
block or not.Those are two different thing, One is Throwing and another is Handling the exception and compiler will make his nose tilted on second one only...:p
From the JavaDoc :
So, by providing
try...catch
implementation, you are requesting compiler to do some more thing than just printing exception.Another specific reason :
If you will observe the compiled code of above example by
javap -c Test.class
you will find an Exception table will be created.So, When compiler won't find any code that is not throwing exception in try block, an compile time error will be there.
and Exception table will not be generated in case of
throws
.