java - In java, why is Exception the base class and not RuntimeException?

16,475

Firstly, the base class of all things that can be thrown is Throwable (not Exception).

Under Throwable are two subclasses: Exception and Error.

Under Exception is RuntimeException.

Of these 4 main classes, RuntimeException and Error are unchecked (may be thrown without having to be declared as being thrown).

The idea behind RuntimeException being unchecked is that it's typically a programming error and that normal good practice should avoid them (eg ArrayIndexOutOfBoundsException or NullPointerException) and to require them to be caught would clutter up the code massively.

The reason Errors are unchecked is that basically, there's nothing you can to about it if one happens, eg OutOfMemoryError etc.

That leaves all other Throwables, ie subclasses of Exception, must be declared as thrown or caught. The idea behind this is that checked exceptions can be "handled by the caller". eg FileNotFoundException (we know what this means and should know what to do if we get one).

The Java designers didn't always get this right. SQLException is checked, but there's no realistic way to recover - do I have a syntax error in my query? is the database refusing conections? who knows, but I do know I can't "handle" it.

Share:
16,475
AStupidNoob
Author by

AStupidNoob

Updated on June 20, 2022

Comments

  • AStupidNoob
    AStupidNoob almost 2 years

    The Java specification requires that if an exception is thrown, it is either handled by a try/catch statement, or that the function is declared with "throws XYZException". This has the exception of RuntimeException, where it is OK if this is thrown without being caught.

    This might sound like a matter of opinion, but the more I think about it, the more it seems really counter-intuitive:

    Why is it that we have a RuntimeException extending Exception?

    When I first started doing Java, I thought ALL exceptions had to be caught in that way, and it made sense because all exceptions extend Exception. It seems like a violation of OOP to have a RuntimeException exception exception :P. Since RuntimeException makes throws kinda redundant, why didn't Java allow all exceptions at runtime in the first place, adding a throws only when you want to force the caller to handle that type of exception?

    Examples:

    void noThrows() {
        throw new Exception();
    }
    

    ... no errors.

    void hasThrows() throws AnyBaseOfXYZException {
        throw new XYZException();
    }
    

    ... no errors.

    void testFunction() {
        hasThrows();
    }
    

    ... fails since "hasThrows" throws AnyBaseOfXYZException, and this is not handled

    void testFunction() {
        try {
            hasThrows();
        } catch (AnyBaseOfXYZException e) {
            ...
        }
    }
    

    ... no errors.

    I'd thought about maybe some kind of "CompileTimeException" that extends Exception, but when you give it enough thought, it just can't work without being as ugly as RuntimeException.

    Basically, why did Java decide to force all exceptions to require throws except for RuntimeExceptions, when all exceptions could be runtime exceptions except when otherwise stated with throws?