CS 261 University of Puget Sound Spring, 2020
 
Computer Science II
Abstract Data Types and their Implementations, Some Basic Algorithms,
Object-oriented Problem Solving, and Efficiency
 

Warning: This course is under development. Although the basic structure of this course is largely established, nothing on this Web site should be considered official or even possibly correct.
DO NOT MAKE PLANS BASED ON THE CONTENTS OF THIS SITE UNTIL JANUARY, 2020.

Exceptions and Exception Handling in Java

Summary

This laboratory provides background and practice with utilizing exceptions and exception handling within a Java program.

Introduction

In implementing the Rational.java class, the resulting code handled many circumstances with constructors, arithmetic operations, and "toString" methods. However, coding in the previous lab did not address the possibility that the denominator of a fraction might be zero. In much computing, such matters typically are addressed in one of four ways:

  1. The Ostrich Approach: Ignore the issue and hope it does not arise.

  2. Identify a Special (or Sentinel) Return Value: For division by 0, return NULL rather than a Rational object.

  3. Set a [global] error variable: If an operation goes wrong, identify the problem within a variable that is stored globally. If processing proceeds without trouble, a "no-error" value is stored in the relevant variable.

  4. Throw an Exception: Interrupt the normal flow of processing, and switch to a section of code designed for such matters.

In practice, each of these approaches is used to address issues in various operating systems and programming languages. For example,

Some Drawbacks

Although each approach can work reasonably well in some contexts, each also has some obvious disadvantages.

The Exception Approach

With the use of exceptions, the idea is to break the normal flow of processing, using an exception. In general, an exception is any event that may require a change in the normal flow of processing. In Java, a program "throws" an exception when the unusal event is detected. Statements in the block calling the method then"catch" the exception, allowing appropriate actionto be taken. To illustrate this approach for the Rational example, a divide method might be revised as follows:

    Rational divide (Rational divisor) throws Exception {
       int numerator = num * divisor.denom;
       int denominator = denom * divisor.num;
       if (denominator == 0){
          throw new ArithmeticException ();
       }
       return new Rational (numerator, denominator);
    }
  

With this refinement, normal processing is interrupted in a main method or application if division within a computation tries to divide with a denominator being zero. With this approach normal processing can continue simply, but throwing the exception can be reasonably clean. The structure of code within main or an application can have the form

  try {
     .
     Rational rat1 =
     Rational rat2 =
     .
  result = div (rat1, rat2);  
     .
     .
     .
  } catch 
    (ArithmeticException e) {
        System.out.println ("attempted division by 0:");
        System.out.println ("   Exception caught:  " + e);
    }  

In this try ... catch block, the try keyword indicates that processing should shift to the catch section, if any exceptions are encountered in the block. The block itself can then focus on regular arithmetic computations.

More generally, a program can contain several try ... catch blocks (even one for each arithmetical operation), and exceptions can be handled differently in each one if desired.

Steps for this Lab

In this lab, you will want to use your complete Rational class that you developed earlier, based on the skeleton code in Rational.java.

  1. Following the discussion earlier in this lab, modify your Rational from the Working with Java and Eclipse:

  2. Expand your testing from step 1 to include two or more sets of arithmetic operations, each with its own try ... catch block and each including division by zero. Each catch block should print something different, so output from the program will indicate which block(s) encountered a problem.

  3. The initial documentation for the Rational class specified, "Assertion:  throughout, denom > 0"

    Modify the constructor(s) as needed, so that an InvalidObjectException is thrown, if the user tries to create a Rational object with 0 in the denominator.

    Adjust your main or testing application appropriately to provide testing that includes the attempted construction of a fraction with a denominator of zero.

  4. Review the data fields and the getters and setters for the Rational class. Which, if any, of these should be private, eliminated completely, or modified? In each case, justify your conclusion.

  5. Discussion: Code development involving factions with zero in the denominator could be handled in several ways. Write a paragraph (at least 6 sentences) to address the following.


created 18 January 2020
revised 18 January 2020
Valid HTML 4.01! Valid CSS!
For more information, please contact Henry M. Walker at walker@cs.grinnell.edu.