Exceptions

When a problem occurs, Java attempts to transfer control to a method that can deal with the problem. Such methods are called exception handlers. An exception handler can either correct the problem (fault handlers), gracefully terminate the program (trap handlers), or simply ignore the problem.

Java recognizes two types of problems: errors and exceptions. Exceptions can be further divided into I/O exceptions and runtime exceptions:

Errors are system errors, such as memory exhaustion. Programmers should not attempt to handle these. Runtime exceptions are programming errors, such as a bad cast, an out-of-bounds array access, or a null pointer access. I/O exceptions occur when bad things happen to an otherwise good program, such as trying to open a file that doesn't exist.

As in C++, the syntax for throwing an exception is:

throw(exp); where exp is an instance of the Java Exception class (or some class derived from it): exp = new Exception(gripe); and gripe is a string describing the nature of the problem: String gripe = "Bad Input!"; Throwing an exception causes control to return immediately to the calling procedure, which either handles the exception or implicitly throws the exception to its calling procedure.

If a method explicitly or implicitly throws an exception, it must explicitly declare so in its header:

String farenToCent(String s) throws Exception {...} To handle an exception explicitly or implicitly thrown by a method, the method must be called inside a try block. The handler code is placed in an immediately following catch block: try
{
   farenToCent("42"); // might throw an exception
   // etc.
}
catch(Exception exp)
{ // the exception handler
   System.err.println("Error: " + exp);
   System.exit(1);
}
Example

The following program computes and displays sqrt3(x) for x = 16 and x = -16. In the second case, the attempt to compute sqrt(-16) throws a custom "negative number" exception, which is handled by the caller of the caller. We begin by declaring an exception class. This step isn't necessary if you're happy with existing exception classes:

import java.io.*;

class NegativeNumberException extends IOException
{
   public NegativeNumberException(double irritant)
   {
      super("non-negative number expected, not " + irritant);
   }

   public NegativeNumberException()
   {
      super("non-negative number expected");
   }
}

 

class ExceptionDemo
{
   public static double squareRoot(double x) throws NegativeNumberException
   {
      System.out.println("Entering squareRoot()");
      if (x < 0)
      {
         NegativeNumberException exp
            = new NegativeNumberException(x);
         throw(exp);
      }
      System.out.println("Exiting squareRoot()");
      return Math.sqrt(x);
   }

 

   public static double cubeOfSquareRoot(double x) throws NegativeNumberException
   {
      System.out.println("Entering cubeOfSquareRoot()");
      double temp = squareRoot(x); // may implicitly throw exception here
      System.out.println("Exiting cubeOfSquareRoot()");
      return temp * temp * temp;
   }

 

   public static void displayCubeOfSquareRoot(double x)
   {
      double result = 0;
      System.out.println("Entering displayCubeOfSquareRoot()");
      try
      {
         result = cubeOfSquareRoot(x);
      }
      catch(NegativeNumberException e)
      {
         System.err.println("Error: " + e);
         // more steps here?
      }
      System.out.println("result = " + result);
      System.out.println("Exiting displayCubeOfSquareRoot()");
   }

 

   public static void main(String[] args)
   {
      System.out.println("Entering main()");
      System.out.println("calling displayCubeOfSquareRoot(16)");
      displayCubeOfSquareRoot(16);
      System.out.println("calling displayCubeOfSquareRoot(-16)");
      displayCubeOfSquareRoot(-16); // trouble
      System.out.println("Exiting main()");
   }
} // ExceptionDemo

Program Output Entering main()
calling displayCubeOfSquareRoot(16)
Entering displayCubeOfSquareRoot()
Entering cubeOfSquareRoot()
Entering squareRoot()
Exiting squareRoot()
Exiting cubeOfSquareRoot()
result = 64.0
Exiting displayCubeOfSquareRoot()
calling displayCubeOfSquareRoot(-16)
Entering displayCubeOfSquareRoot()
Entering cubeOfSquareRoot()
Entering squareRoot()
Error: NegativeNumberException: non-negative number expected, not -16.0
result = 0.0
Exiting displayCubeOfSquareRoot()
Exiting main()