Reputation: 3735
In Cay Horstmann's Java 9 book, it says
Integer.parseInt(String str);
"it throws an unchecked NumberFormatException".
NumberFormatException inherits from RuntimeException. When I look at the Java 11 docs, it is declared in the signature. So calling methods must handle it at some point.
public static int parseInt(String s) throws NumberFormatException
isn't it now a checked exception - because the compiler can check its usage?
Update: Does the compiler check if the NumberFormatException
is handled by the caller? I don't see any benefit that calling methods (or even those far from the calling method) are never required by the compiler to catch the checked exception.
Upvotes: 1
Views: 975
Reputation: 719426
... isn't it now a checked exception - because the compiler can check its usage?
No.
JLS 11.1.1 says this:
The checked exception classes are all exception classes other than the unchecked exception classes. That is, the checked exception classes are
Throwable
and all its subclasses other thanRuntimeException
and its subclasses andError
and its subclasses.
That is the definition.
You can declare any exception in a throws
clause, but only checked exceptions are checked by the compiler to ensure that they are handled or declared in the calling method.
So calling methods must handle it at some point.
Incorrect.
A throws
for an unchecked exception doesn't alter the way the compiler handles the code, and doesn't alter any runtime behavior either. The throws
does not make an exception checked. It does not force the calling method to handle the exception.
The (ostensible) reason for declaring an unchecked exception in a throws
clause is to document the fact that the exception may be thrown by the method. This will translate into text in the method's javadocs that the programmer can (should) read to understand the method and how to use it.
In your example, NumberFormatException
is a subclass of RuntimeException
, so it is NOT a checked exception; see the javadoc. However, a programmer still needs to know that parseInt
can throw an (unchecked!) NumberFormatException
, so they have included throws NumberFormatException
in the parseInt
declaration anyway.
OK, so what would be the effect of the semantic you are suggesting?
What it would mean is that exceptions are checked or unchecked based on what the method's throws
clause. So one method might declare that NumberFormatException
is checked, and another that it is not checked.
I think that the compiler could cope with this. But I'm not sure that a typical programmer could. For example, it makes the decision of what to put in a method's throws
clause a lot harder.
The second thing is that this would allow programmers to effectively ignore checked exceptions by not using any throws
clauses. But the original Java rationale was that it was better to force the programmer to deal with the exceptions ... because that leads to code that is more robust. Java checked exceptions (as currently specified) eliminate a significant class of programmer errors at compile time.
To avoid that second problem you would need some extra syntax that allowed the programmer to explicitly mark an exception as unchecked. For example
public void method1() throws AnException, AnotherException {
...
}
public void method2() {
try {
method1();
} catch (AnException e) {
} unchecked AnotherException
}
whether the unchecked
clause means that AnotherException
no longer is treated as checked ... and doesn't need to be declared by method2
.
(But I can imagine many programmers abusing an unchecked
construct if it was provided by the language.)
Upvotes: 4
Reputation: 103707
It could have been, but the language simply isn't designed that way.
A few things just are.
All source files secretly have import java.lang.*;
in them. Whether you write it or not. The compiler acts exactly as if it was there.
All methods and constructors act as if they have throws RuntimeException, Error;
on them. You can't make a method not have this. Whatever you decree is just added to that pile. Therefore, any method that invokes a method that is known to throw NumberFormatException
doesn't need to handle it, as it has declared that it throws it onwards (because all methods are defined as throws RuntimeException
even if you didn't write that, and NFEx is a subtype of RuntimeException.
An intriguing alternate take on exceptions could be that anything that is declared explicitly is therefore checked, and anything that is not is therefore unchecked, and java grows a new throw
instruction that doesn't require that you also declare that type in your throws
block.
But, java doesn't work that way, and as far as I know, no language out there does.
NB: So why are some methods declared explicitly as throwing some unchecked exception type, why do some source files include import java.lang.*;
? Because the author of said file thinks it helps readability. That import statement is hard to rhyme and indeed you rarely see that. But explicitly declaring that you throw an unchecked type is somewhat common. The reason they do this is solely for readability. It does nothing. It's a comment that isn't in /* */
. Comments do absolutely nothing either and yet people do write that.
Upvotes: 3