java - In java, why is Exception the base class and not RuntimeException?
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.
AStupidNoob
Updated on June 20, 2022Comments
-
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 withthrows
?