I've got a coding standards meeting in just over an hour and I need a quick answer to this one.
Common wisdom among experienced Java programmers is that you don't throw or catch java.lang.Exception (with rare exceptions - no pun intended). The reason you don't do this is that the statement
catch (java.lang.Exception ex) {...}
will also catch unchecked Exceptions, and in most cases this is not what is intended.
We already have a lot of legacy code written by existing team members where they catch a subclass of java.lang.Exception, log an error, and rethrow the subclass as java.lang.Exception.
I need to convince them that
- They need to stop writing code like this.
- Existing code that uses this anti-pattern needs to be fixed
Number 2 means a fair amount of refactoring.
It will shorten the argument at the meeting if I can show an article or blog entry by one of the Java community heavyweights that makes this point (i.e. Joshua Bloch, James Gosling). My google-fu hasn't turned up anything so far.
Does anyone know of an article or blog by a respected Java guru that says that you shouldn't throw or catch java.lang.Exception?
Quick answers are much appreciated.
Dean
-
1just want to show you that question: stackoverflow.com/questions/237585/… Some nice answers in itbastianneu– bastianneu2009年10月16日 15:02:13 +00:00Commented Oct 16, 2009 at 15:02
-
I read that one before posting this. A couple of the answers and comments say the same thing, but I'm looking for an authority. This will result in a fair amount of refactoring so it would help to have an expert's opinion to back me up.Dean Schulze– Dean Schulze2009年10月16日 15:45:26 +00:00Commented Oct 16, 2009 at 15:45
9 Answers 9
Here's something: Java Tip 134: When catching exceptions, don't cast your net too wide (JavaWorld)
Effective Java (Second Edition) by Joshua Bloch might have something on this in Chapter 9 (Exceptions), although I couldn't quickly find anything about not catching Exception.
Here is a Q&A from JavaWorld about the question (also points to Java Tip 134) - it also explains why you sometimes have to break the rule of not catching Exception or even Throwable.
Comments
See this article from Brian Goetz (the concurrency wizard) who has his own insight as well as quoting Josh Bloch in Effective Java
Comments
There is no common ground here. You will find two groups:
Those who hate checked exceptions will catch and wrap them in a
RuntimeExceptionof some kind.Those who hate
RuntimeException
The first group hates to riddle their code with try...catch, especially since in most cases, you can't handle the exception when you first see it. Think IOException: It could be thrown for every byte that your read. What's the low level code to do about it? It has to rethrow it so someone higher up can add some useful context to the error (like which file you were reading).
The other group wants to see what could go wrong. RuntimeException effectively hides this.
There is a simple fix, BTW: Make Exception extend RuntimException. Insane? Not really. If you do that with JDK 7, you get two compile errors.
The next step would be to have all Java compilers enumerate all runtime exceptions and list them in the throws entry in the class file. You still don't have to catch them but now, you'll know which ones could happen.
Lastly, extend the IDEs to display this. And presto, both groups could be happy. Unfortunately, this won't happen.
5 Comments
SQLException and IOException are clearly runtime exceptions in my view since in my experience, they are thrown more often because of a programming error rather than because of a condition that the caller could actually handle.Here is Bruce Eckel's viewpoint on checked exceptions in general, which is that in most cases they are a bad idea. Maybe that will have something that you can use.
Comments
where they catch a subclass of java.lang.Exception, log an error, and rethrow the subclass as java.lang.Exception. I need to convince them that they need to stop writing code like this.
I agree they should use another tactic, but for different reasons. There's not much sense in catching an exception just to log it and rethrow it.
An alternative is: don't catch the exception and let some higher up code (like a Java EE Filter, or try/catch in your main() method) catch and log all uncaught exceptions. Then you ensure each exception is only logged once, and you know all uncaught exceptions will be logged.
If you need to add extra information to the exception, catch it, change the message and rethrow it. I usually use a RuntimeException for this:
} catch (Exception originalException) {
throw new RuntimeException("user name was " + userName, originalException);
}
3 Comments
Here is a very insightful article
Summary:
Use checked exceptions for rare but valid contingencies that relate to the purpose of your code. Client code should know how to handle these.
Use unchecked exceptions for faults that shouldn't happen but do. (Server down, classpath misconfigured, SQL syntax error, etc.) The IT guy who manages the server, or the developer who just passed bad SQL to prepareStatement() should know how to fix these problems. Faults should propagate up to the logging layer so the info doesn't get lost.
Comments
it's a long article but this proposes you:
- use checked exceptions when the client expects this error to occur regularly and must handle it (ex: user-entered data did not pass validation)
- use unchecked exceptions for unexpected conditions (ex: DB server went down)
In theory, #1 (expected errors) should have their own exception type, and the only place that should catch a #2 (a RuntimeException) is some type of top-level handler that catches the exception, logs it, and shows the user an error message, and even here, you should probably catch Throwable to make sure any uncaught exceptions are handled.
Following these guidelines, you shouldn't catch Exception since it doesn't fit either of the above criteria (meaning, it's not a RuntimeException and it's not a specialized Exception sublcass to indicate an expected error).
4 Comments
I guess the point is that if you don't know how to handle a specific exception then you shouldn't catch it. It should propagate to a higher level in the hopes that it might know what to do with it. Catching exceptions too early leads to exceptions being swallowed silently and makes it impossible to do anything useful with them beyond logging.
Imagine what would happen if FileInputStream's constructor were to log an exception internally if you tried opening a file that did not exist, but didn't indicate this failure to your code. It's fine that the error gets logged but your code would like to catch this exception and do something useful with it (such as prompting the user for a new filename). If they were to catch (Exception) you wouldn't be able to do this.
Comments
If you have a copy of Josh Bloch's Effective Java to hand, I know he covers exception handling in a fair bit of detail there. I don't have access to it at present so I can't summarise it or give you page references, but I'm pretty sure he's got some good arguments for not catching java.lang.Exception.