Why is it discouraged to throw a generic (java.lang.Exception) exception, when it is usually sufficient to handle most conditional failures within a method? I understand tha
If you throw more specific exceptions, that does not stop any calling code from dealing with all of them in one Exception
catch block. Being more specific is more documenting as to what type of errors occur, making it easier for programmers to deal with them separately.
Additionally, by throwing "Exception" itself you're basically telling callers of your code that they can't rule out any class of exception. An IOException
might occur, as might a NumberFormatException
, etc.
As always: It depends.
I think there is a difference between API that you expose to others. That may live for some time. In that case you don't know what the caller considers best for his case.
On the other hand there always is code that you use internally only for yourself. Than it might be sufficient to throw an generic exception. But remember, that you might want to change some exception handling later on. That will be harder when all error cases are mangled together.
The problem is that Exception
is also the superclass of RuntimeException
, which encompasses some stuff that shouldn't be caught as it indicates a problem with the programming rather than an exceptional condition that arises from context. You don't want to catch a BufferOverflowException or UnsupportedOperationException under normal circumstances. Besides, throwing separate Exception types gives the calling code control over how to handle each one. Boilerplate is reduced in Java 7 with the new multi-catch feature.
Generally you want to know what happened in you app and only catch specific exceptions and let the program fail (or go higher in execution order) when you get the exception that you don't specifically target. Catching Exception will catch them all and in some cases you wouldn't know your program is failing.
Dittos to GH. I would have used "null pointer exception" and "out of memory exception" as more obvious examples of the kind of exceptions you probably don't watch to catch in the same block with your true application exceptions.
I'd also add that it pays to go to a little effort for future expandability. If you throw generic Exceptions all over the place, and later you decide that you need to catch some exceptions and not others, it can be a major pain to go back and change them all. But if you just create the exceptions you need as you go along, it's not that big a deal. Creating a new exception class that just accepts a constructor with a message takes, what, 5 lines of code? It's good investment for the future.
Like many things in programming, it's a question of how far you go. I usually create a rather generic "BadInputException" in almost every project I work on, and throw this any time user inputs fail validation criteria. Then I can just catch BadInputException and throw the message on the screen. If I create a complex class that throws exceptions for inconsistent data and that sort of thing, I usually create an exception class for it. Like if I create a "TalkToDatabase" class, I'll create a "TalkToDatabaseException". (Maybe more than that if there are multiple kinds of exceptions I know I want to catch, but at least the one.)
And by the way, I don't know if you're thinking of this, but I would strongly discourage examining the text of an error message to determine the type of error. I've seen programs where they throw generic Exceptions all over the place, and then in catch blocks they have code like
// Very bad idea! Don't do this!
catch (Exception ex)
{
if (ex.getMessage().equals("Invalid foo"))
... handle bad foo ...
else if (ex.getMessage().equals("Plugh is over maximum"))
... handle bad plugh ...
... etc ...
}
It would be much better to just make separate Exceptions for these cases. Not only will processing be much more efficient, but suppose you do the above and somebody comes along later and decides to change the message to "Foo is invalid"? The program will still compile, but it won't work correctly.