likejudo
likejudo

Reputation: 3735

If you explicitly throw an unchecked exception in your code, isn't it now a checked exception - because the compiler can now check if it's handled?

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

Answers (2)

Stephen C
Stephen C

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 than RuntimeException and its subclasses and Error 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

rzwitserloot
rzwitserloot

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

Related Questions