James McMahon
James McMahon

Reputation: 49609

In Java, is using throws Exception instead of throwing multiple specific exceptions good practice?

While looking through the Spring MVC framework I noticed that, unless I misunderstand, its developers favor throws Exception instead of throwing multiple exceptions.

I realize that at the core of this question is the checked versus unchecked exceptions debate, avoiding that religious war, is it a good practice to use throws generic exception?

Upvotes: 15

Views: 16273

Answers (15)

Julien Chastang
Julien Chastang

Reputation: 17774

Brian Goetz touches on some of these issues here. Also see Effective Java 2nd Edition by Josh Bloch. He devotes a whole section on Exceptions. In addition, Rod Johnson, the founder of the Spring Framework, details his thoughts about Java Exception handling in J2EE Design and Development. You may or may not agree with his exception handling philospohy, but at least it may make more sense why they took the decisions they did.

alt text
(source: sun.com)
alt text

Upvotes: 1

Gary Kleppe
Gary Kleppe

Reputation: 39

In general, "throws Exception" is rarely a good idea.

In running computer code, runtime errors can be roughly put in two broad categories. There are those that are the result of bad code — maybe logic errors in the called method itself, or bad inputs having been passed to it. Then there are those problems that are due to circumstances beyond the programmer's control. Maybe the system is trying to open a file that another process has just deleted or access a remote server across a network that just went down.

If the first kind of exception happens, there's no reason for your program to catch it and continue. It should fail cleanly and obviously, making it clear what happened so that you can be alerted to fix whatever went wrong.

The second kind of exception is the kind you want to catch. You don't know whether these problems will occur on any given run, but you can have a pretty good idea of WHERE in your code they COULD occur -- basically, anytime you need to depend on a resource outside your program's control.

Declaring thrown exceptions is essentially a contract between the authors of a method and the clients using it, telling you what you should expect could go wrong. A blanket "throws Exception" is equivalent to throwing up your hands and saying that clients must be ready for ANYTHING to go wrong, even problems that should've already been found and fixed during early debugging. Callers must either catch these exceptions -- and will usually just eat them and continue since the contract is so broad that they have no idea where the problem came from -- or throw them on upwards, forcing somebody else to deal with the same issues.

Upvotes: 1

Tim
Tim

Reputation: 196

IMO the biggest reason for not throwing Exception is that it forces our clients to catch(Exception e) if they're truly interested in taking some action.

The problem with catch(Exception e) is that Exception, while checked, is also the superclass of RuntimeException and so forces the client to catch all RuntimeExceptions too.

Sadly there is no catch(CheckedException e) technique. Assuming your poor client had no need to catch RuntimeExceptions, they have to perform an instanceof check and re-throw if its a RuntimeException.

Upvotes: 3

WhyNotHugo
WhyNotHugo

Reputation: 9916

List every exception. This way:
* It is clearly define what CAN go wrong.
* Users of your class can know EXACTLY what exceptions they should handle.

Also, an overriding method should do THE SAME THING as the overridden, but in a different manner. Hence, how could you have another exception, which IS NOT a subclass of an already thrown exception? You shouldn't. Besides, you SHOULD NOT throw new exceptions in a subclass, since a subclass is supposed to be able to replace it's parent class, hence if it gets passed on as "p" to

public void method(Parent p);

How would "method" know it has to handle some new exception? It shouldn't need to. And it means improper design (either of the parent class, or the subclass).

Upvotes: 1

Everyone
Everyone

Reputation: 2376

Tricky.

Ideally specifying an exception forms part of the contract, telling the user what exceptions may be expected. This helps them decide what to handle, and what not.

When writing a framework, or a library though it's impossible to say -

abstract T func(...) throws A, B, C;

because any class that extends the container of func(...) may potentially override func too.

I've myself had to use the looser specification of 'throws Exception' but as a rule of thumb

  • Provide strict exception specifications for private methods (in the context of this discussion, i deem methods to be private in the sense that their contract is immutable), loose specification for all others.

Upvotes: 0

Paul Tomblin
Paul Tomblin

Reputation: 182772

No, absolutely not. You should specify what exceptions you're going to throw so the caller can do the right thing with each one. If you don't, "throws Exception" gets passed up the chain, and the best the callers can do is printStackTrace() and die.

Update: To counter some of the "what if I override the method" objections, I'd go a bit further and say that any time you have a package that throws exceptions (as opposed to passing up an exception from a caller), you should declare an exception class in that package. Thus, if you're overriding my "addToSchedule() throws ScheduleConflictException", you're perfectly able to subclass ScheduleConflictException to do what you need.

Upvotes: 18

Joshua
Joshua

Reputation: 43188

I actually removed checked exceptions from the compiler.

This works better than one might guess.

Right now, a good portion of configuration errors show up as unhandled exceptions but reading the first line of text makes the real problem obvious.

I've been planning to modify the top level exception handler to display an error message box rather than an unhandled exception box for a couple of exception types (mainly IOException). I already have an ErrorMessage exception that it checks for.

Upvotes: 1

Karl
Karl

Reputation: 2945

Throwing exception can also cause loads of issues with transaction management in J2EE. The use of catch exception is pure evil!

I award you no kittens!

Upvotes: 0

Jay
Jay

Reputation: 27464

You need to distinguish between generic code and more specific code.

Consider the return types of functions as an analogy. If you're writing a class like "ArrayList", you want it to be very general, so the parameters and return values are often generic "Object"s. But when you're writing code more specific to your application, like a "getRetiredEmployees" function, it would be a very bad idea to return Object. You more likely want to return Employee[] or something of that sort.

So sure, a framework like Spring is going to expect generic Exceptions because it doesn't have any idea what exceptions your particular application is going to throw. There's no way the authors of Spring could know that you were going to throw an "EmployeeNotInSpecifiedDepartment" exception or whatever. How could they? But if you're writing the sendPensionChecks function and you call getRetiredEmployees, you can reasonably expect to know specific exceptions that that function might throw, and what you should do to handle them.

Clint Miller brings up a valid point about not knowing how a class might be extended. I concede this is a problem with making your exceptions specific. But going from there to "just make everything a generic Exception" is giving up too easily. It's like saying that because someone someday might extend our getRetiredEmployees function to in some cases return EmployeeSpouse's along with Employee's, that therefore we should just give up and make the return type Object. If this is code you are using internally and you control, it's a non-problem: If you need to add a new Exception to a function, then add it. If this is an API that you are publishing to the world, then yes, the problem is much trickier. I'd say the general solution is to try to think out rationally what exceptions make sense and include them all, even if they aren't all presently implemented. If one of your clients is doing something completely unanticipated, oh well, that's a problem for which there is no easy answer.

Making everything generic is not the right answer, because it makes everything difficult to to understand, difficult to maintain, and difficult to verify accuracy.

Upvotes: 1

matt b
matt b

Reputation: 139921

What makes sense for a library such as Spring MVC, which needs to be open enough to fit all sorts of different use cases, does not necessarily make sense for you to follow when writing a specific application. This is one of those cases.

If you are referring to classes such as the Controller interface which as a method signature such as

handleRequest(HttpServletRequest request, HttpServletResponse response) 
   throws Exception

This is likely because, from the perspective of the Spring classes which call into your Controller (such as DispatcherServlet), they don't care what type of Exception your code calls - library code such as DispatcherServlet only needs to know that this class may throw an Exception and therefore is capable of handling Exception in the general case.

In other words, DispatcherServlet doesn't need to know what specific type(s) of Exception your Controller may throw - it's going to treat any of them as an "error". This is why the method signature is throws Exception.

Now, the API authors could have made the signature use a custom exception type as SpringMvcException, but that would only have the effect of forcing you to handle any checked exception types in your handleRequest method and simply wrap them, which is tedious make-work boilerplate code. So, since pretty much everything with Spring is designed to make it as easy and lightweight for you to integrate with as possible, it's easier for them to specify that the interface method merely throws Exception.

Upvotes: 16

Mike Pone
Mike Pone

Reputation: 19320

Yes and no. yes it's "convenient" to just throw or catch one exception and be done, but it really hurts you in any attempt to gracefully recover from an exception. Certain exceptions can and should be handled gracefully so you program doesn't die a horrible death. If a method just throws exception, I have no idea what went wrong and so I can't have any hope to fix and recover from a problem.

One possible error and solution include :

when parsing ints - NumberFormatException. We could have a default value

Bottom line, I think it's a better practice to keep the individual exceptions.

Upvotes: 0

Clint Miller
Clint Miller

Reputation: 15371

Here's the problem with throwing specific exceptions... Suppose someone extends your class and wants to override your method. Suppose their new implementation needs to throw a different type of exception. (How would you ever be able to predict what exceptions an overriding method might need to throw?) The person writing the overriding method only has two choices: 1) handle the exception himself (likely a bad choice), or 2) wrap the real exception in one of the allowed exception types and re-throw.

But option 2 has two problems. First, when you dump your exceptions to your log files, you'll get long ugly chains of nested exceptions. More importantly, you'll lose your ability to catch specific exceptions. For example, suppose the overriding method calls another method that talks to the database and throws a DeadlockException if the resulting SQL caused a deadlock. The overriding method has to catch this exception, wrap it in one of the allowed types, and rethrow. This makes it impossible for code further up the stack to catch and detect the DeadlockException.

Your question ultimately gets into the heart of the debate about checked versus unchecked exceptions. You can Google and find lots of arguments for both sides of the debate. I think that ultimately, if you believe in checked exceptions, you should be very explicit about what exceptions a method throws. If you don't like checked exceptions, you should declare every method to throw Exception. I fall in the latter camp.

By the way, for people who don't like checked exceptions, I don't like the idea of using RuntimeException's everywhere. The problem is that you'll likely need to incorporate a 3rd party library that uses Exception's rather than RuntimeException's. Then, your code will have to catch all Exception's from the library and wrap them in RuntimeException's. That creates a mess.

So, if I were starting a Java project from scratch again, I'd just declare every method to throw Exception.

Upvotes: 7

Samuel Carrijo
Samuel Carrijo

Reputation: 17929

IMHO, all design discussions and recommendations say good things about what should be done IN GENERAL, and they have a principle that support them. But usually these recommendations don't apply to all cases.

In the case of exception handling, the idea of using checked exceptions is that it is usually good to catch and manage the exception differently, depending on what you want. But, if you are sure they will all be caught and managed the same way, there's no point in checking the types all the time.

Upvotes: 2

Aaron Maenpaa
Aaron Maenpaa

Reputation: 122850

No.

Throwing Exception forces calling code to catch exception which they will probably not want to do for all kinds of reasons.

Upvotes: 3

foobarfuzzbizz
foobarfuzzbizz

Reputation: 58637

In my opinion yes, because this allows you to throw any exception you want.

As your program grows, you might need to throw a different exception than you had originally thought about. If you defined each individual exception type, you would have to modify the methods signature and in turn modify all methods that called it to properly process the new exception.

Just using 'throws Exception' allows any method calling your method to properly handle any methods you have listed, but whenever you add new exceptions into your function, it won't break these other methods. (Though you should probably update them to handle the new exception, but this is not required.)

Upvotes: 1

Related Questions