Why throws
, on a method, is part of its signature? It seems strange to include it. Here is an example where it is in the way:
@Overide
public void foo() {
throw new UnsupportedOperationException();
}
If anyone were to see this method from the outside, they might try to use it without knowing that it is not supported. They would only learn it on trying to run the code.
However, if they could do something like this they would know by looking at the method that it is not supported and if UnsupportedOperationException
was not extending RuntimeException
, they would get a compilation error. EDIT1: But this is not possible because throws
is part of the signature so override will not work.
@Overide
public void foo() throws UnsupportedOperationException {
throw new UnsupportedOperationException();
}
This question concerns Java's design, so I know that it might be hard to answer without one of the people that work on it drops by and answers it, but I was hoping that maybe this question has been asked to them before or that there might be an obvious reason to have it this way to explain why.
The throws
part does not indicate that the method is required to throw the mentioned exception(s), not even at particular occasions. It only tells that the function is allowed to do so.
Including throws UnsupportedOperationException
will consequently not mean that the method is unsupported. Besides the UnsupportedOperationException
is a RuntimeException
so a method may throw
that anyway.
Now for the reason one would require it in the signature of the method, it boils down to the ability to have checked exceptions at all. For the compiler to be able to decide if a method can only throw the specified exceptions it must be able to decide that the methods that it calls can't throw uncaught exceptions.
This means for example that overriding a method means that you can't add exceptions that might be thrown, otherwise you would break the possibility to verify that a method that calls that method can't throw anything else than it has specified. The other way around would be possible (but I'm not sure if Java supports that), overriding a method that may throw with one that may not throw.
So for example:
class B {
int fubar(int) throws ExceptionA {
}
int frob(int) throws ExceptionA {
return fubar(int);
}
}
class D extends B {
int fubar(int) throws ExceptionB {
}
}
Now frob
is specified to possibly throw
only ExceptionA
, but in calling this.fubar
it would open the possibility that something else is thrown, but fubar
is defined to possibly only throw
ExceptionA
. That's why the D.fubar
is an invalid override since that would open up the possibility that this.fubar
actually throws ExceptionB
and the compiler wouldn't be able to guarantee that frob
doesn't throw ExceptionB
.