Skip to main content
Engineering LibreTexts

10.5: Creating and Throwing Your Own Exceptions

  • Page ID
    15123
  • \( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \) \( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)\(\newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\) \( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\) \( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\) \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\) \( \newcommand{\Span}{\mathrm{span}}\) \(\newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\) \( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\) \( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\) \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\) \( \newcommand{\Span}{\mathrm{span}}\)\(\newcommand{\AA}{\unicode[.8,0]{x212B}}\)

    [pg-sec-throws]

    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.20 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. 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.

    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 (Fig. 10.14) 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 (Fig. 10.21).

    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 (Fig. [fig-intfield2]).

    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

    The IntFieldTester class (Fig. [fig-intbound]) has the design and functionality shown in Figure [fig-numformat]. It 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.

    -4.5pc

    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.addWindowListener(new WindowAdapter() { 
          public void windowClosing(WindowEvent e) {
            System.exit(0);   // Quit the application
          }
        });
      } // main()
    } // IntFieldTester

    Define a new Exception named FieldIsEmptyException, which is meant to be thrown if the user forgets to enter a value into a IntField.

    Modify the IntField.getInt() method so that it throws and catches the FieldIsEmptyException.


    This page titled 10.5: Creating and Throwing Your Own Exceptions is shared under a CC BY 4.0 license and was authored, remixed, and/or curated by Ralph Morelli & Ralph Wade via source content that was edited to the style and standards of the LibreTexts platform; a detailed edit history is available upon request.