Question

I have been in both situations:

  • Creating too many custom Exceptions
  • Using too many general Exception class

In both cases the project started OK but soon became an overhead to maintain (and refactor).

So what is the best practice regarding the creation of your own Exception classes?

Was it helpful?

Solution

The Java Specialists wrote a post about Exceptions in Java, and in it they list a few "best practices" for creating Exceptions, summarized below:

  • Don't Write Own Exceptions (there are lots of useful Exceptions that are already part of the Java API)

  • Write Useful Exceptions (if you have to write your own Exceptions, make sure they provide useful information about the problem that occurred)

OTHER TIPS

Don't do what the developers at my company did. Somebody created an [sic] InvalidArguementException that parallels java.lang.IllegalArgumentException, and we now use it in (literally) hundreds of classes. Both indicate that a method has been passed an illegal or inappropriate argument. Talk about a waste...

Joshua Bloch covers this in Effective Java Programming Language Guide [my bible of first resort on Best Practices] Chapter 8. Exceptions Item 42: Favor the use of standard exceptions. Here's a bit of what he says,

Reusing preexisting exceptions has several benefits. Chief among these, it makes your API easier to learn and use because it matches established conventions with which programmers are already familiar [my emphasis, not Bloch's]. A close second is that programs using your API are easier to read because they aren't cluttered with unfamiliar exceptions. Finally, fewer exception classes mean a smaller memory footprint and less time spent loading classes.

The most commonly reused exception is IllegalArgumentException. This is generally the exception to throw when the caller passes in an argument whose value is inappropriate. For example, this would be the exception to throw if the caller passed a negative number in a parameter representing the number of times some action were to be repeated.

That said, you should never throw Exception itself. Java has a well-chosen, diverse and well-targeted bunch of built-in exceptions that cover most situations AND describe the exception that occurred well enough so that you can remedy the cause.

Be friendly to the programmers who have to maintain your code in the future.

My rule of thumb is when the client (the caller) might reasonably want to do something different, depending on the type of exception thrown, the additional exception types are warranted. More often than not, however, the extra exception types are not needed. For instance, if the caller is writing code like

try {
     doIt();
} catch (ExceptionType1 ex1) {
     // do something useful
} catch (ExceptionType2 ex2) {
     // do the exact same useful thing that was done in the block above
}

then clearly the additional exception types are not needed. All too often I see (or am forced to write) code like this because the code being called was overzealous in its creation of new exception types.

If I can't find an exception that has a name describing what type of error was caused then I make my own.

That's my rule-o-thumb.

Basically, each job deserves an own exception. When you catch exceptions, you don't distinguish different instances, like you would normally do with objects, therefore you need different subtypes. Using too many custom exceptions is a case which I see hardly occurring.

One advice would be to create exceptions as needed, and if it becomes apparent that one exception type is a duplicate of another, refactor the code by merging the two. Of course it helps if some thought goes into structuring exceptions from the beginning. But generally, use custom exceptions for all cases that have no 1:1 correspondence to existing, situation-specific exceptions.

On the other hand, NullPointerExceptions and IndexOutofBoundsExceptions might actually often be appropriate. Don't catch these, though (except for logging) as they're a programming error which means that after throwing them, the program is in an undefined state.

My own rule of thumb:

I never throw Exception, except in unit tests when what you throw is irrelevant and theres no reason to spend any extra time on it.

I create my own custom exception type for errors occuring in my custom business logic. This exception type is used as much as possible for recasting other exceptions, except in cases where it makes sense for the client to have visibility into what actually occurred.

While creating your own exception:

  • All exceptions must be a child of the Throwable Class

  • If you want to write a checked exception that is automatically enforced by the Handle or Declare Rule, you need to extend the Exception Class

  • If you want to write a runtime execption, you need to extend the Runtime Exception Class.

Don't eat exceptions, throw them https://stackoverflow.com/a/921583/1097600

Avoid creating your own exception. Use the below ones that are already there.

IllegalStateException
UnsupportedOperationException
IllegalArgumentException
NoSuchElementException
NullPointerException

Throw unchecked exceptions.

Example

public void validate(MyObject myObjectInstance) {
    if (!myObjectList.contains(myObjectInstance))
        throw new NoSuchElementException("object not present in list");
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top