views:

504

answers:

6

Possible Duplicate:
When to choose checked and unchecked exceptions

Why does Java as a language have both checked and unchecked exceptions. What purpose do they serve?

Note: I'm not asking when I should use them, or how to code them, but what they add to the language.

+4  A: 

They add a differentiation between errors that the designer of a library feels must be caught, and ones that they feel the programmer shouldn't handle.

For example it might be reasonable for a program to handle bad input from a user, but if something goes wrong with the underlying OS and threads starts to die without reason, it isn't something that the program should be expected to handle.

Alexander Kjäll
Unfortunately, that argument fails in practice - see my answer about IOException and SQLException...Java's libraries screwed up the distinction, and everything went downhill from there...
MetroidFan2002
+3  A: 

I think Sun initially thought it would be a good idea because the programmer is forced to handle the exception. However, many years later, pretty much everyone agrees they are a bad, unneccessary addition.

One of the main issues (apart from cluttering code) is that they leak abstractions form lower layers to higher layers (such as rmi remote exceptions)

gommo
Do you have any links to articles criticising checked exceptions? I disagree with your second point - If you design your checked exception hierarchy carefully enough you can prevent calling code from ever being aware of implementation specific errors. If necessary you can always wrap a specific exception as the underlying cause of an exception you expose via your API.
Adamski
The beauty of the Exception class is it allows exceptions to be chained. In the situation you've described with RemoteException, this should be being caught and rethrown as something specific with the RemoteException being set at the 'cause'.
Nick Holt
To summarize the previous two comments: The annoyances of checked exceptions have to be worked around by adding useless boilerplate code. Which is pretty much what people are criticizing.
Michael Borgwardt
@Adamski: Read Joshua Bloch's chapter on Exceptions in Effective Java (the most recent edition): he talks about leaking abstractions through Exceptions. This is when a higher level is forced to handle (or declare that it throws) checked exceptions coming from a particular lower level implementation. For instance say the high level should not know if the low level is logging events, leet alone that it logs to a SQL database vs. an XML file. Therefore if it has to handle a SQLException or an XMLStreamException the abstractness of the lower level API has leaked away.
Jim Ferrans
@Jim - Thanks; I'll take a look. In your example I would typically define a DAO interface that threw a "general" DataAccessException. Then for the SQLDAO implementation I would catch and rethrow SQLExceptions as DataAccessExceptions, preventing the abstractness from leaking away. Is the general feeling that checked exceptions are bad because you have to get into the practice of doing this, whilst it's unnecessary for unchecked exceptions?
Adamski
+4  A: 

Personally, I think checked exceptions were a mistake in Java.

That aside, designating both checked and unchecked exceptions allows a library to differentiate between recoverable and unrecoverable errors. By making all recoverable errors throw checked exceptions, a library/language can force a developer to handle the edge cases they might otherwise paper over.

The big problem with this:

try{
  myCode();
}catch(Exception e){ //Do nothing }

Additionally, in most cases it really is best to just throw up your hands and pass an exception up when one occurs. By forcing checked exceptions to be declared, a method that really doesn't care if an error occurs ends up having dependencies (in terms of compatibility, but also code-smell and others) it really shouldn't.

Kevin Montrose
Very true. For some exceptions, I ended up writing a special function just to not having to write the try catch over and over again.
Burkhard
+3  A: 

Checked and unchecked exceptions invokes a bit of a religious argument - Java fell one side of the fence, C# the other.

In Java checked exceptions should be used when the calling code can recover from the error as where unchecked exceptions are used when there's a critical error (with perhaps the exception - no pun intended - of NullPointerException) that the calling code is unlikely to be able to recover from.

Personally I like to have both available to me generally favouring checked exceptions because they allow me to force the calling code to deal with an error situation that a developer might otherwise have ignored (although the infamous empty catch block side-steps this).

Nick Holt
+7  A: 

The theory for checked exceptions is simple.

When designing an interface, think of exceptional cases that can occur, and will occur, with the normal state of a method call. Declare these exceptions in your interface, as the programmer will have to handle them directly.

For example, a bank account withdraw method may declare an OverdraftException, which is an expected exception - a withdrawal may fail due to overdraft, but this type of failure may be handled differently by the client code (one may decide to completely deny the withdrawal, another may decide to apply a huge penalty and allow for a negative balance to be recorded, another may decide that their client is allowed to draw from a different account).

However, runtime exceptions were supposed to be programming errors that weren't supposed to be handled directly - such as NullPointerExceptions, which only occur if methods take invalid arguments or don't check for such cases directly.

This is a good theory. However, Java messed up with its implementation of Exceptions, and this threw the book of this theory out the window.

There are two cases that I will illustrate where Java messed up with its implementation of Exceptions. These are IOException and SQLException.

An IOException occurs anytime, anywhere a stream in the IO libraries of Java messes up. This is a checked exception, however. But, generally you cannot do anything but log that an error occur - if you're simply writing to the console, what can you reasonably be expected to do if you suddenly get an IOException when you're writing to it?

But there's more.

IOException also hides stuff like file exceptions and network exceptions. They may be subclasses of IOException floating around for that, but it is still a checked exception. If your writing to an external file fails, you can't really do much about it - if your network connection is severed, ditto.

SQLException is the same way. Exception names should show what happened when they are called. SQLException does not. SQLException is thrown any single time any possible number of errors are encountered when dealing with a database - MOST OF WHICH THAT HAVE NOTHING TO DO WITH SQL.

Therefore, programmers typically get annoyed with handling exceptions, and let Eclipse (or whatever IDE they're using) generate blocks like this:

try {
thisMethodThrowsACheckedExceptionButIDontCare();
}
catch(Exception e) {
e.printStackTrace();
}

However, with RuntimeExceptions, these intentionally bubble up and eventually get handled by the JVM or container level. This is a good thing - it forces errors to show up and then you must fix the code directly instead of ignoring the exception - you may still end up just printing the stack trace (hopefully logging it instead of printing to the console directly), but then there will be an exception handler that you were forced to write because of a real problem - not because a method said that it might possibly throw an Exception, but that it did.

Spring uses a DataAccessException to wrap SQLExceptions so that you don't have to handle them as a checked exception. It makes code much cleaner as a result - if you expect a DataAccessException, you can handle it - but most of the time you let it propagate and be logged as an error, because your SQL should be debugged by the time you release your application, meaning the DataAccessException is probably a hardware issue that you could not resolve - DataAccessException is a much more meaningful name than SQLException, because it shows that access to data failed - not that your SQL query was nessecarily at fault.

MetroidFan2002
@Metro: You said what I was trying to say, only much better. Thank you. Cheers. Keith.
corlettk
+1  A: 

I don't think there's anything at all conceptually wrong with checked exceptions... but they do tend to suck mightilly in practice, because (especially early) library developers over-use them.

Also the "catch or declare" requirement does NOT fit well with interfaces.

My basics thoughts are: "Stuff that goes wrong" comes in two basic flavours: recoverable, and unrecoverable... Ergo: Business Exceptions and System Errors.

For instance: What do you (the library developer) expect me (the application programmer) to do about recovering from a failure in a call to SomeStream.close()? Yes, I definately need to be made aware that something has gone horribly wrong, but really my only option is to terminate the program/request/process/thread which tripped over it. I cannot be reasonably expected to even attempt to recover from the situation... Ergo: It's an uncoverable error, and therefore I shouldn't be forced to write a lot of highly repitious boilerplate catch-blocks which don't handle the problem at every level of the (potentially very deep) callstack. Therefore I believe it would be better if "catch all" checked exceptions such as IOException had never been invented... CloseException extends UncheckedIOException would be more appropriate, IMHO.

Also, if I had a time machine I'd go back in time and plead with the Java gods for:

  • interface Throwable
    • abstract class Exception
      • abstract class CheckedException
      • abstract class UncheckedException
    • class Error

Also: I'd love to see a @FaultBarrier class-annotation, which makes the compiler enforce: All exceptions (especially unchecked ones) must be caught or explicitly thrown. The most horribilest hunk of system I've ever worked on was riddled with throwings of raw RuntimeException; It's enough to make you weep.

Cheers. Keith.

corlettk