views:

2575

answers:

14

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?

A: 

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.)

samoz
+17  A: 

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.

Paul Tomblin
In most cases that's what callers end up doing anyway, and littering your signatures with dozens of exception signatures (or wrapping exceptions) is no better than just declaring "throws Eception". Yeah, I'm fully in the camp of those who believe that checked exceptions are an utterly failed experiment.
Michael Borgwardt
@Michael Borgwardt, I don't know if the misuse of something like checked exceptions by most developer is really a valid argument against checked exceptions in the first place. Let's fix the idiot developers, not the language concepts that they don't understand.
matt b
There *is no* correct way to use checked exceptions in an application of non-trivial size. It is a fundamentally flawed concept because it forces the immediate client of a method to deal with the exception, which runs directly against the very concept of exceptions - allowing the developer to deal with them at the appropriate point in the call stack.
Michael Borgwardt
+1  A: 

No.

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

Aaron Maenpaa
+2  A: 

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.

Samuel Carrijo
Have a look at Java 7, they're implementing a mechanism to allow you to catch a series of exception types and handle them the same way using a simple "<? extends Throwable> [| <? extends Throwable>] e" idiom.
Beau Martínez
+5  A: 

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.

Clint Miller
+1 for a good argument on the other side, but I still disagree with you.
Paul Tomblin
Have a look at Java 7, http://tech.puredanger.com/java7
Beau Martínez
Beau, are you referring to the proposed new method to convert a checked exception into an unchecked exception? That would be a nice addition.
Clint Miller
Good arguments, but doesn't this just suggest that method signatures that are likely candidates for overriding should be more general anyway? If a method is declared private on a public class or is accessible but documented so that overrides ought to call the supertype's implementation, why not be very specific with exception types?
David Berger
+8  A: 

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.

matt b
Good point, I have been mulling it over since I posed the question and I was going to post something similar to this answer. Glad you saved me some typing and beat me to it.
James McMahon
A: 

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.

Mike Pone
+1  A: 
Julien Chastang
+1  A: 

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.

Jay
A: 

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!

Karl
A: 

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.

Joshua
A: 

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.
Everyone
A: 

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).

Hugo
+1  A: 

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.

Tim