Custom Exceptions: Differentiate via many subclasses or single class backed with enum?
I'm looking to implement my own set of Exceptions
for a projects I am currently working on. The project relies on a core framework with a base framework exception MyFrameworkException
(I am also writing this framework).
For any given project I would like to throw several different types of Exceptions
and I can't decide between using multiple subclasses or a single subclass with some form of an Enum
as a constructor parameter.
In both cases I have:
public class MyFrameworkException extends Exception { /*...*/ }
Option 1:
public class MyProjectBaseException extends MyFrameworkException { /*...*/ }
public class SpecificExceptionType1 extends MyProjectBaseException { /*...*/ }
public class SpecificExceptionType1 extends MyProjectBaseException { /*...*/ }
public class SpecificExceptionType1 extends MyProjectBaseException { /*...*/ }
Then, throughout the project I would throw the specific exception for any problem that occurs.
Option 2:
public class MyProjectException extends MyFrameworkException {
public static enum Type {
SpecificType1, SpecificType2, SpecificType3
}
public MyProjectException( Type type ) { /*...*/ }
}
Here I would always throw MyProjectException
with the specific enum type for any problem that occurs. I'd provide some mechanism so that a s开发者_Go百科witch statement could be performed on any MyProjectException
based on the type enum.
What's the best way to handle exceptions in projects, especially those sharing a common infrastructure? Are the two options above good solutions? Why or why not? And what are any better solutions?
The chief disadvantage to Option 2 (a common exception + enum) is that you lose some of the utility of checked exceptions. A method pretty much has to say simply "something framework-related might go wrong":
public void foo()
throws MyFrameworkException
...rather than "x or y might go wrong":
public void foo()
throws SomethingWentWrongException, SomethingElseWentWrongException
It means a function that may need to handle one framework exception has to be prepared to handle any of them, whereas if you're specific, a function need only be prepared to handle the exceptions that are thrown by the framework methods it calls.
So for me, a hierarchy such as Option 1 (it needn't be quite so flat, if a structure suggests itself) is the way to go. That said, there are people who don't like checked exceptions at all, and for them I suspect the above is not a compelling argument. :-)
Edit And picking up duffymo's point: I've assumed you were talking about exceptions you really did have to create. Absolutely throw standard exceptions wherever it makes sense (which is nearly everywhere). Don't create your own MyFrameworkIllegalArgumentException
, for instance, just use IllegalArgumentException
(or its various subclasses).
I would go with exceptions extending java.lang.RuntimeException with descriptive class names.
If you have so many business-specific exceptions that this becomes oppressive, it means you're probably doing it wrong.
See Joshua Bloch's advice about favoring standard exceptions.
I wouldn't inherit from a generic MyFrameworkException
, as long as you dont provide any functionality in there common to all projects. Else, always extend Exception.
Normally you should throw meaningful exceptions at domain/layer boundaries. So regarding your question, you should go with option 1, having in mind the point above. Option 2 would increase code complexity, as you will always have to check for the exception type to determine what went wrong. Let the exception class speak for itself.
精彩评论