6

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?

AStupidNoob
  • 1,980
  • 3
  • 23
  • 35
  • Here's an example of a pretty open discussion about almost the same thing from the `Related Questions`: http://stackoverflow.com/questions/613954/the-case-against-checked-exceptions?rq=1. Why close this? It doesn't go better anywhere else... – AStupidNoob Jul 13 '13 at 13:56

3 Answers3

9

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.

Bohemian
  • 412,405
  • 93
  • 575
  • 722
  • Ah OK, I didn't know about `Throwable` and `Error`. Things are making a lot more sense now. Still, any idea why they forced all exceptions to be caught by default? – AStupidNoob Jul 13 '13 at 13:21
  • 1
    @AStupidNoob they don't force _all_ exceptions to be caught by default, only checked exceptions; and those are subclasses of `Exception` except `RuntimeException` and subclasses. – fge Jul 13 '13 at 13:22
  • My problem here is more about the fact that RuntimeException extends Exception, and hence just as I could create a subclass of Exception and throw it, I'd need `throws Exception` to allow it to compile. Not so for RuntimeException... so it seems like a needless exception to the rule, why not make all Exceptions "unchecked" and use throws to force checking? – AStupidNoob Jul 13 '13 at 13:27
  • 1
    Because Java was designed to prevent developers from making common problems. Most Exceptions are checked in order to have the developer handle these cases properly. Making all exceptions unchecked allows lazy developers to not handle exceptions at all, a very dangerous approach that should not happen. – Jan Henke Jul 13 '13 at 13:33
  • I understand that. As far as I know, that's why they implemented the `throws` declaration. But why force it upon writers of functions that ALL exceptions, aside RuntimeExceptions, be checked? Why not allow them the option to do it on a case by case basis using `throws` as it is now? – AStupidNoob Jul 13 '13 at 13:38
  • 2
    I really suggest you read a good Java book. There is a good rationale behind this behaviour, more than I could explain in 550 characters here. It is really about the fact that `RuntimeExceptions` only occur if the developer made an error, every other `Exception` is the result of something out of the control of the developer, e.g. user input, i/o operation. Because the latter can occur at any moment in time, developer are forced to handle it properly. `RuntimeExceptions` on the other should not occur in a well written program, thus there is no need to handle them. – Jan Henke Jul 13 '13 at 13:46
  • OK, I'll keep that in mind. I guess you're probably right: since RuntimeExceptions shouldn't be happening at all anyway, what's the point of doing it the way I proposed? It's basically the same thing either way. I'll accept this answer. Thanks a lot all! – AStupidNoob Jul 13 '13 at 13:50
  • Of course, you can't blame SQLException on the original Java architects. – Hot Licks Jul 13 '13 at 13:52
  • Note that the checked/unchecked discussion is irrelevant to why RuntimeException extends Exception which is what is actually being asked. – Thorbjørn Ravn Andersen Jul 13 '13 at 14:32
0

In some cases you want to have a catch that catches all exceptions: checked and unchecked. Java's design decision allows you to achieve that with catch (Exception e) { ... } If unchecked exceptions (exceptions that extends RuntimeException) were not extending Exception then you had to use two catch clauses.

Itay Maman
  • 30,277
  • 10
  • 88
  • 118
  • That's not what I mean. I want to know why, by default, exceptions are not all runtime exceptions unless otherwise stated. – AStupidNoob Jul 13 '13 at 13:15
  • 1
    Exceptions are not by default 'checked'. Whenever you write a new exception class you have to specify its superclass. If you specify 'exception' it checked. If you specify 'runtime-exception' it is unchecked. There is no default. You have to explicitly set its category. – Itay Maman Jul 13 '13 at 13:18
  • I know what you're saying, and I understand that. As I can create a class that extends Exception and throw it, I'd still need throws Exception to allow it to compile. But for RuntimeException: even though it extends Exception, it doesn't need a throws. It makes it seem like in Java, there is no way to throw an unchecked Exception. When I was learning Java, I just assumed this. It was only when I searched up how to throw an unchecked exception that I found out about RuntimeException. I'm just curious as to why it was designed that way, so thanks for answering anyways. – AStupidNoob Jul 13 '13 at 13:47
0

This might be related to topic of check and uncheck exception. From RuntimeException

RuntimeException and its subclasses are unchecked exceptions. Unchecked exceptions 
do not need to be declared in a method or constructor's throws clause if they can 
be thrown by the execution of the method or constructor and propagate outside the
method or constructor boundary.

Check exception is to be use for case that recoverable when the program is executed. So it makes perfect sense to force programmer writing the class to declare it in a method definition. By doing so the caller will be force to catch it or re throw it.

However uncheck exception is for a case that is unrecoverable and thus it is better to terminate. This case is rarely happen (usually happen when the code is still being developed) and thus this usually indicate a programmer error or a very fatal bug that usually need to fix by the class writer and is not recoverable by the client of the class.

Nuntipat Narkthong
  • 1,387
  • 2
  • 16
  • 24
  • I understand that, what my point is that since RuntimeException extends Exception, it stands to reason that a function that throws a RuntimeException also throws an Exception and should thus declare `throws Exception`. This is confusing, and I'd like to know why Java made that choice when all exceptions could be runtime exceptions unless otherwise stated. – AStupidNoob Jul 13 '13 at 13:13