How to Create Custom Exceptions in Java

By Doug Lowe

You can create custom exceptions in Java. As a programmer, you probably have a good grasp on exceptions, but here, you will use inheritance to create exceptions of your own.

Tracing the Throwable hierarchy

You use the try/catch statement to catch exceptions and the throw statement to throw exceptions. Each type of exception that can be caught or thrown is represented by a different exception class. What you may not have realized is that those exception classes use a fairly complex inheritance chain.

image0.jpg

The following paragraphs describe the classes in this hierarchy:

  • Throwable: The root of the exception hierarchy is the Throwable class. This class represents any object that can be thrown with a throw statement and caught with a catch clause.

  • Error: This subclass of Throwable represents serious error conditions that reasonable programs can’t recover from. The subclasses of this class represent the specific types of errors that can occur. If the Java Virtual Machine runs out of memory, for example, a VirtualMachineError is thrown. You don’t have to worry about catching these errors in your programs.

  • Exception: This subclass of Throwable represents an error condition that most programs should try to recover from. Thus, Exception is effectively the top of the hierarchy for the types of exceptions you catch with try/catch statements.

    With the exception (sorry) of RuntimeException, the subclasses of Exception represent specific types of checked exceptions that must be caught or thrown. Note that some of these subclasses have subclasses of their own. The exception class named IOException, for example, has more than 25 subclasses representing different kinds of I/O exceptions that can occur.

  • RuntimeException: This subclass of Exception represents unchecked exceptions. You don’t have to catch or throw unchecked exceptions, but you can if you want to. Subclasses of RuntimeException include NullPointerException and ArithmeticException.

If your application needs to throw a custom exception, you can create an exception class that inherits any of the classes in this hierarchy. Usually, however, you start with the Exception class to create a custom checked exception.

Creating an exception class

To create a custom exception class, you just define a class that extends one of the classes in the Java exception hierarchy. Usually you extend Exception to create a custom checked exception.

Suppose that you’re developing a class that retrieves product data from a file or database, and you want methods that encounter I/O errors to throw a custom exception rather than the generic IOException that’s provided in the Java API. You can do that by creating a class that extends the Exception class:

public class ProductDataException extends Exception
{
}

Unfortunately, constructors aren’t considered to be class members, so they aren’t inherited when you extend a class. As a result, the ProductDataException has only a default constructor. The Exception class itself and most other exception classes have a constructor that lets you pass a string message that’s stored with the exception and can be retrieved via the getMessage method.

Thus you want to add this constructor to your class, which means that you want to add an explicit default constructor too. So now the ProductDataException class looks like this:

public class ProductDataException extends Exception
{
 public ProductDataException
 {
 }
 public ProductDataException(String message)
 {
  super(message);
 }
}

Although it’s possible to do so, adding fields or methods to a custom exception class is unusual.

Throwing a custom exception

As for any exception, you use a throw statement to throw a custom exception. You usually code this throw statement in the midst of a catch clause that catches some other, more generic exception. Here’s a method that retrieves product data from a file and throws a ProductDataException if an IOException occurs:

public class ProductDDB
{
 public static Product getProduct(String code)
  throws ProductDataException
 {
  try
  {
   Product p;
   // code that gets the product from a file
   // and might throw an IOException
   p = new Product();
   return p;
   }
   catch (IOException e)
   {
   throw new ProductDataException(
    "An IO error occurred.");
   }
 }
}

Here’s some code that calls the getProduct method and catches the exception:

try
{
 Product p = ProductDB.getProduct(productCode);
}
catch (ProductDataException e)
{
 System.out.println(e.getMessage());
}

Here the message is simply displayed on the console if a ProductDataException is thrown. In an actual program, you want to log the error, inform the user, and figure out how to continue the program gracefully even though this data exception has occurred.