Skip to main content
Logo image

Java, Java, Java: Object-Oriented Problem Solving, 2024E

Section 10.6 Creating and Throwing Your Own Exceptions

Subsection 10.6.1 A New IntOutOfRange Exception

Like other Java classes, the Exception class can be extended to handle cases that are not already covered by Java’s built-in exceptions. Exceptions that you define will be handled the same way by the Java interpreter, but you will have to throw them yourself.
For example, Figure 10.6.1 shows the design of an exception that can be used for validating that an integer is less than or equal to a certain maximum value.
Figure 10.6.1. The IntOutOfRange exception.
It would be coded as follows:
/**
  *  IntOutOfRangeException reports an exception when
  *    an integer exceeds its bound.
  */
public class IntOutOfRangeException extends Exception {
    public IntOutOfRangeException (int Bound) {
      super("The input value exceeds the bound " + Bound);
    }
  }
The class extends Exception and consists entirely of a constructor method that calls the superclass constructor. The argument passed to the superclass constructor is the message that will be returned by getMessage() when an instance of this exception is created.

Activity 10.6.1.

Try the num values 10 and 11 below to see this exception in action.

Subsection 10.6.2 IntFieldClass

Now let’s consider an example where this new exception will be thrown. Suppose we wish to constrain the IntField class that we developed previously (Figure 10.5.6) so that it will only accept numbers that are less than a certain bound. First, let’s modify IntField so that its bound can be set when an instance is created. We want its bound to be an instance variable with some initial value, and we want to provide a constructor that can be used to override the default (Figure 10.6.2).
Figure 10.6.2.
This leads to the following revision of IntField:
public class IntField extends JTextField {
    private int bound = Integer.MAX_VALUE;
    public IntField(int size, int max) {
        super(size);
        bound = max;
    }
   // The rest of the class is unchanged for now
  } // IntField
Our new constructor has the signature IntField(int,int), which doesn’t duplicate any of JTextField’s constructors. This is good design, because in extending a class, we want to be careful about the effect that our definitions have on the original methods in the superclass. Superclass methods should be overridden by design, not by accident. If a method is redefined inadvertently, it might not function as expected by users of the subclass.
Note how we have handled the problem of setting the default value of the bound. Integer.MAX_VALUE is a class constant that sets the maximum value for the int type. It’s an appropriate value to use, because any valid int that the user types should be less than or equal to MAX_VALUE. Given these changes to IntField, let’s now incorporate our new exception into its getInt() method (Listing 10.6.4).
This new version of getInt() throws an exception if the integer entered by the user is greater than the IntField’s bound. Here again, it is difficult to handle this exception appropriately in this method. The method would either have to return an erroneous value—because it must return something—or it must terminate. Neither is an acceptable alternative. It is far better to throw the exception to the calling method.
import javax.swing.*;
public class IntField extends JTextField {
    private int bound = Integer.MAX_VALUE;
    public IntField (int size) {
        super(size);
    }
    public IntField(int size, int max) {
        super(size);
        bound = max;
    }
    public int getInt() throws NumberFormatException,
                               IntOutOfRangeException {
        int num = Integer.parseInt(getText());
        if (num > bound)
            throw new IntOutOfRangeException(bound);
        return num;
    } // getInt()
} // IntField
Listing 10.6.4. The revised IntField class containing the revised getInt() method.
The IntFieldTester class (Listing 10.6.5) provides a simple GUI interface to test the IntField class. It prompts the user to type an integer that is less than 100, and then it echoes the user’s input. Note how the exception is handled in the actionPerformed() method. If an exception is thrown in IntField.getInt(), the actionPerformed() method pops up an error dialog, and the erroneous input is not used. Instead, the user is given another chance to enter a valid integer.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class IntFieldTester extends JPanel
                                       implements ActionListener  {
  public static final int WIDTH = 300, HEIGHT = 300;
  private JLabel prompt = new JLabel("Input an integer <= 100: ");
  private IntField intField = new IntField(12, 100);
  private int userInt;
  private String message = "Hello";
  public IntFieldTester() {
    add(prompt);
    intField.addActionListener(this);
    add(intField);
    setSize(WIDTH, HEIGHT);
  } // IntFieldTester()
  public void paintComponent( Graphics g ) {
    g.setColor(getBackground());            // Clear the panel
    g.fillRect(0, 0, WIDTH, HEIGHT);
    g.setColor(getForeground());
    g.drawString(message, 10, 70);
  } // paintComponent()
  public void actionPerformed(ActionEvent evt) {
    try {
      userInt = intField.getInt();
      message = "You input " + userInt + " Thank you.";
    } catch (NumberFormatException e) {
      JOptionPane.showMessageDialog(this,
       "The input must be an integer.  Please reenter.");
    } catch (IntOutOfRangeException e) {
      JOptionPane.showMessageDialog(this, e.getMessage());
    } finally {
      repaint();
    }
  } // actionPerformed()
  public static void main(String args[]) {
    JFrame f = new JFrame("IntField Tester");
    IntFieldTester panel = new IntFieldTester();
    f.getContentPane().add(panel);
    f.setSize(panel.WIDTH, panel.HEIGHT);
    f.setVisible(true);
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  } // main()
} // IntFieldTester
Listing 10.6.5. An application that uses an IntField object to process integers.

Activity 10.6.2.

Try the IntField class below by entering the invalid values of 101 and 3.5.

Exercises Self-Study Exercises

1. FieldIsEmptyException.
Define a new Exception named FieldIsEmptyException, which is meant to be thrown if the user forgets to enter a value into a IntField.
2. IntField.getInt().
Fork the repl project below. Modify the IntField.getInt() method so that it throws and catches the FieldIsEmptyException (copied from your solution above).
You have attempted of activities on this page.