Java Custom Exceptions and Best Practices

We have been using handling java custom exceptions in our code for almost every industry standard application. Usual approach is to create some custom exception classes extending the base exception handling best practice which might make you more sense.

1) Java Custom Exception Handling – New Approach

1.1. Traditional exception handling

Our new approach uses static inner classes for every new exceptional scenario.

Traditionally, we create a DBException class by extending Exception class. Now, every time we are caught in a situation where there is a need to throw a database related exception, we usually create an instance of DBException, put some information in form of the message and throw it.

Now, let’s consider there are following situations we have identified in which we need to throw DBException:

  1. SQL execution error
  2. No data exist where we expect at least one row
  3. Multiple rows exist where we expect only single row
  4. Invalid parameters error
  5. and many more such cases

The problem with above approach is that in catch block or in application code where these exceptions shall be handled, DBException does not provide enough information to handle each abode listed use cases, uniquely.

1.2. New exception handling with inner classes

Let’s solve the above problem with inner classes where we will create one class per use-case, and then group them inside DBException class.

Lets start with BaseException class which is created as abstract and will be super class of all our exception classes.

// Make this class abstract so that developers are forced to create
// suitable exception types only
public abstract class BaseException extends Exception{
	//Each exception message will be held here
	private String message;

	public BaseException(String msg)
		this.message = msg;
	//Message can be retrieved using this accessor method
	public String getMessage() {
		return message;

Not its time to create out new Exception inner classes.

public class DBExeption
	//SQL execution error
	public static class BadExecution extends BaseException
		private static final long serialVersionUID = 3555714415375055302L;
		public BadExecution(String msg) {

	//No data exist where we expect at least one row
	public static class NoData extends BaseException
		private static final long serialVersionUID = 8777415230393628334L;
		public NoData(String msg) {

	//Multiple rows exist where we expect only single row
	public static class MoreData extends BaseException
		private static final long serialVersionUID = -3987707665150073980L;
		public MoreData(String msg) {

	//Invalid parameters error
	public static class InvalidParam extends BaseException
		private static final long serialVersionUID = 4235225697094262603L;
		public InvalidParam(String msg) {

Here, we created an inner class for each possible error scenario identified in starting. There can be many more extras. It depends on you only to identify and add more classes.

1.3. How to use custom exceptions

Now to understand it’s usefulness, let’s create an exception and throw it. Then we will see the error message in logs.

public class TestExceptions {
	public static void main(String[] args)
			throw new DBExeption.NoData("No row found for id : x");
		catch(Exception e)

Program output:

com.exception.DBExeption$NoData: No row found for id : x
at com.test.TestExceptions.main(

As you can see the log message in exception stack trace, it has become more informative. It clearly tells what is the error. In application code as well, you can check the instance of custom exception and handle accordingly.

2. Advantages of using inner classes as custom exceptions

  1. Foremost advantage is that if you developer has written some doubtful message text, then also you can clearly observe that what was actually wrong.
  2. You can use instance-of comparison in different situation where you handle different exceptional scenarios.
  3. You don’t need to send single exception for a large set of exceptional conditions.
  4. Its easy to write unit test cases for negative cases where you know the exact exception class, you should expect.
  5. Logging is more meaningful and informative.

I hope this post about java custom exceptions has been some information for you. If you have some suggestions, please write to me.

Happy Learning !!

Was this post helpful?

Join 7000+ Awesome Developers

Get the latest updates from industry, awesome resources, blog updates and much more.

* We do not spam !!

17 thoughts on “Java Custom Exceptions and Best Practices”

  1. Creating specific exception types is good idea but grouping them in a Class is not better (at least for me). This is against design principle “Strong Cohession”. Are classes really intended for grouping types or it can be done better with packages ?

    Moreover, using inner classes leads to memory leaks !

    • Packaging them in groups is also a good idea if developers are intelligent enough for using correct class in case of any exception.
      Memory leak? I don’t think so. Can you please elaborate more on memory leak issue?

  2. Hey Lokesh,

    thanks for writing this article. Reminding developers of being mindful with exception handling is a good idea, as it’s too often done in a sloppy way.

    I have a few remarks though:

    * BaseException reinvents the wheel: the class “Exception” already has a way to store a message; no need to duplicate that in BaseException. Just pass the message parameter on to the superclass constructor.

    * BaseException has no constructor that takes a cause-exception (BaseException(String message, Throwable cause)). This is important in case you’re throwing a BaseException (or derived class) as a result of catching another exception. By specifying the original exception as cause, it’s much easier to debug what really happened as if you’re logging the stacktrace, you’ll get information about the inner exception as well.

    A good point you’re making is that having detailed exceptions is often more helpful than using one generic exception for everything. But there’s one thing I don’t get: why do you put them into DBException, as static inner classes? Why not just putting them top-level, without a wrapping class. You get exactly the same advantages of having detailed exceptions, without the weirdness of having so many inner classes.

    • My intention is to group related exception classes in one class, just like we use packages. We can create some classes denoting broad exception categories and then use inner classes to create specific failure cases.

      Apart from above, code example is more to represent idea. Anyone can refine the code as per his/her need.

      • correct me if I’m wrong, but aren’t you using the outer classes just to create a new namespace?

        why do you group your exceptions in one class and not a package? Is it to circumvent the Java restriction to have multiple classes in the same file?

        • Yes, I am trying to create a logical namespace.

          You want to group them in package.. no problem..It will still be beneficial.. at least more than having a generic exception for a group of failures.

          • Yeah, that is (at least for me) the main point here: Create exceptions that are meaningful and describe the problem well enough.

  3. Don’t you think this will create classes for each and every static inner class, which is a huge, if we keep on adding for every error one static class. Pls let me know if am wrong and suggest me..

    • Yes, effort is more than usual. But rewards are far better. Believe me, I have used this technique in one project and it works like a charm. Also, you do not need to teach every tiny detail of exception handling logic to team members, most of the things are self-explanatory. This is highly recommended if you are building a product which you will be managing for 5-10 years.

      • although there are many classes created, but still I believe these classes are accessible just like a method on an object with out a need to create an object for it, other than the parent class like as you shown “new DBExeption.NoData(“No row found for id : x”);”, which will not load JVM with more objects.

        But, I have a doubt, if the growing no of errors increases to support “Logging is more meaningful and informative.”, does that not make the object huge for jvm.

        what happens if there are many scenarios and you created/covered all those in your product/application, where u create an object every time, for exception handling, making JVM fully loaded with many huge DBExeption objects.

        So, do we have to make this “DBExeption” class a singleton?

        Pls let me know if am wrong with my assumption.

        • If such thing happen when there are plenty of exceptions all the time, then application will crash anyway. No fault of object creation logic or JVM load.
          Regarding singleton. I believe we should treat exception objects as first class citizen in our application. If there is an exception occurred, let’s have a fresh new exception object and populate it with complete context information. They have same importance in your application as much DTO objects.
          “DBExeption class as a singleton?”. Need thorough review but its possible.

        • Please never, ever try to use singletons as exceptions! Here’s why:
          * When an exception instance is created, its constructor (the one in class Throwable) automatically captures the stack trace, so you can later (e.g. in a log) find out where excactly the exception was thrown.
          If you’re reusing exception instances, you lose this information. You will always get the stacktrace showing where the instance was originally created, giving you now way to find out where it was actually thrown.

          Regarding your worries about memory:
          Exception instances are not huge. Maybe you are worried about the size of the class DBException in this example. But there’s no need to be. First of all, you’ll not throw instances of this class, but only of its inner classes (which again are rather small). Second, With static inner classes, there’s no real connection between the outer and the inner class. In fact, on the level of the classloader, there’s nearly no difference between a static inner class and a “normal” class.
          And third: exception instances are usually short-lived, so the garbage collector will remove them pretty soon.

          In the end, I think you’ll never see a case where an application runs into out-of-memory problems because of exceptions.

          • Thanks(Rolf Schäuble) for a detailed Information.

            Also, I would like to know in a real time scenario, how and when actually the JVM triggers the grabage collector. is there any specific config changes that we have to do on JVM for this.

Leave a Comment


A blog about Java and related technologies, the best practices, algorithms, and interview questions.