Return to lecture notes index

15-100 Lecture 23 (Friday, October 28, 2005)

Quick Quiz

/*
 * Mark this class compile, WITHOUT removing any code
 * It should print, "Not an integer" if the number isn't an integer
 * It should print, "problem with input" if the readLine() fails
 *
 * Do not use "throws"
 * 
 * You may safely ignore any of my minor syntax errors
 */

class Quiz {

  public static void main (String[] args) {
    
    BufferedReader br = new BufferedReader (new InputStreamReader (System.in));
    
    String line = "";
    int number = 0;
    

    try {

      line = br.readLine();
      number = Integer.parseInt(line);
      System.out.println ("100 * the number is " + 100*number);


    }
    catch (IOException e) {
      System.out.println ("Problem with input.");
    }
    catch (NumberFormatException nfe) {
      System.out.println ("Not an integer");
    }
    catch (Exception e) {
      System.out.println ("Unknown error occured: " + e.getMessage());
    }

  }
}

A More Complex Example

In class today, we developed a more sophisticated example that employed exeptions. Below is the end result of that effort. Discussion follows.

import java.io.*;

class NameGame {


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



  private static final String FIRST_NAME = "Greg";
  private static final String MIDDLE_NAME = "Michael";
  private static final String LAST_NAME = "Kesden";
  private static final int MAX_RETRIES = 3;
  
  
  private static char getOption (String prompt, String options) 
    throws MenuChoiceException {
    
    BufferedReader br = new BufferedReader (new InputStreamReader (System.in));
    char option = '';
    
    System.out.println (prompt);
    
    try {
      option = br.readLine().charAt(0);
    }
    catch (IOExcpetion ioe) {
      throw new MenuChoiceException ("Unable to read choice, IO problem.");
    }
  
    boolean legalOption = false;
    
    for (int retry = 0; retry < MAX_RETRIES; retry++) {
      for (int index = 0; index < options.length(); index++) {
    
        if (option == options.charAt(index))
          legalOption = true, break;
      }
      
      if (legalOption) break;
    }
    
    if (legalOption)
      return choice;

    // if the for loop goes through all the options and then does not
    // find the correct char's, the Exception is then thrown   
    throw new MenuChoiceException ("Too many retries");
   }

  public static void main (String[] args) {
    boolean quit  = false;
 
     
    while (!quit) {
      char choice = '';
      
      try {
        choice = getOption("F, M, L, or Q", "FMLQfmlq");
      }
      catch (MenuChoiceException mce) {
        System.out.println ("A lot of retries...please pay attention.");
        System.out.println ("The choices are 'F, M, L, or Q.");
        continue;
      }
      
      switch (choice) {
    
        case 'f':
        case 'F':    System.out.println (FIRST_NAME);
              break;
            
        case 'm':
        case 'M':    System.out.println (MIDDLE_NAME);
              break;

        case 'l':
        case 'L':    System.out.println (LAST_NAME);
              break;
     
        case 'q':
        case 'Q':  quit = true;
        break;
        
      } // switch 
    } // while (!quit)
  } // main
}

Observation #1: Defining A New Type of Exception

Above, we defined a new type of Exception. Nothing special -- basically "cookie cutter." The only thing to notice here is that it is "private". The reason for this is that it never makes its way out of our class -- so why make it accessible to others?

  private class MenuChoiceException extends Exception {

    public MenuChoiceException (String message) {
      super (message);
    }
    
  } 

Observation #2: Handling The IOException

Notice that the possibility of an IOException from the br.readLine() is managed using a try-catch, instead of the previously-familiar "throws" clause:

    try {
      option = br.readLine().charAt(0);
    }
    catch (IOExcpetion ioe) {
      throw new MenuChoiceException ("Unable to read choice, IO problem.");
    }

Observation #3: The Options String

The way we verified that the user made an allowed choice is a bit unique. We create a String that contains each of the single-character options. We then walk through this String trying to match the user's choice against one of its characters. If we match -- hurray! If, after considering each option within the string, we do not -- it is an error.

    boolean legalOption = false;

    for (int retry = 0; retry < MAX_RETRIES; retry++) {
      for (int index=0; index < options.length(); index++) {

        if (option == options.charAt(index))
          legalOption = true, break;
      }

      if (legalOption) break;
    }

Observation #4: Check out the "throw"

Once we exit the loop, legalOption either remains false -- or it has been changed to true because it matched a valid option. If it became true -- we return the user's choice. This is an example of the normal control flow in a Java program.

But, if it isn't true, we make use of Java's exception-handling mechanism. This is done by using "throw." We generate a "new" [MenuChoice]Exception -- and then "throw" it to start the Exception handling.

    boolean legalOption = false;

    for (int retry = 0; retry < MAX_RETRIES; retry++) {
      for (int index=0; index < options.length(); index++) {

         ...     

      }
    }

    if (legalOption)
      return choice;
    
    // if legalOption is false it will then throw this Exception
    throw new MenuChoiceException ("Too many retries");
   }

In order for this to work, we needed to include the "throws" clause in the method's declaration. This documents the possibility of the Exception to a programmer who might call this method -- and it allows Java to ensure that the programmer acknowledged this possibility with a try-catch block or with an "throws" clause upstream in the call chain.

  private static char getOption (String prompt, String options)
    throws MenuChoiceException {

Observation #5: Catching the Exception

The main() method, which calls getOption(), is not delcared to "throw" any type of Exception. This is because the Exception is properly handled within the method via a try-catch block.

Note below that the main method contains no "throws clause":

  public static void main (String[] args) {

Notice below that the getOption() method, which can throw a MenuOptionException, is surrounded with a try-block. Notice that this try-block preceeds an applicable catch-block. In particular, the catch-block catches exactly the MenuOptionException.

while (!quit) {
  try {
    // click on the link to see the method getOption("F, M, L, or Q", "FMLQfmlq")
    choice =  getOption("F, M, L, or Q", "FMLQfmlq");
  }
  catch (MenuChoiceException mce) {
    System.out.println ("A lot of retries...please pay attention.");
    System.out.println ("The choices are 'F, M, L, or Q.");
    continue;
  }
}