Lab 10: Java API, Exceptions, and Collections


Activities:

  1. Familiarize yourself with the Java Application Programmers Interface (API)
  2. Use exceptions to detect and handle errors
  3. Use the Java Collections framework to group multiple elements into a single unit

Lab Preparation

Download the provided zip file and unzip it. Create a new Eclipse project named Lab10. Add the given code to the project and link the external JAR jpt.jar to the project. You should have the following Java files:


Activity 1: Getting to Know the Java API

Go to the Java API at http://java.sun.com/j2se/1.4.2/docs/api/. Bookmark this page! When coding you will often use classes that are provided for you by Java. The Java API describes these classes and lists all of the fields and methods of these classes that are available to you.

The front page of the Java API lists all of the packages provided by Java. A package is a collection of related interfaces and classes.

Tips For Quickly Finding Class Specifications

The left frame of the API page lists all classes alphabetically. If you want the specifications for a specific class you can click in this frame and use your web browsers search function to find that class. For example, find the ArrayList class. Another way to quickly find Java API specifications is to search Google for "java api class x", where x is the name of the class you're searching for. For example, the search "java api class arraylist" returns the specifications for class ArrayList as the first result.

The Anatomy of a JavaDoc

All of the specifications are in a JavaDoc format. JavaDocs are automatically generated from source code based on specifically formated comments that the programmer adds for each class and each method. We won't cover the format of such comments here, but it's pretty easy to do yourself. For more details, see How to Write Doc Comments for the Javadoc Tool.

Lets use the ArrayList JavaDoc as an example.

The top of the JavaDoc lists the other classes that ArrayList extends and implements. In this case, ArrayList extends from the classes Object, AbstractCollection, AbstractList, and implements the interfaces Cloneable, Collection, List, RandomAccess, Serializable.

Next is a general description of the class. In this case, the JavaDoc says that ArrayList is a "Resizable-array implementation of the List interface."

Following this is a summary of fields, constructors, and methods provided by ArrayList. In general, classes will provide very few public fields and the JavaDoc will contain mostly specifications of methods. Look over some of the methods provided by ArrayList. We will be using a similar classes when cover the Java Collections framework in activity 3.

The method summaries provide headers (return type, name, and arguments) and a short description of the method's functionality. More detailed descriptions are linked from these summaries and appear farther down on the same page.


Activity 2: Using Exceptions

Exceptions provide a general method for dealing with errors that occur during the execution of a program. When an error occurs, an exception object is created. This exception can then be detected and handled smoothly, instead of causing the entire program to fail.

Catching Exceptions

Exceptions are either automatically created by Java when certain types of errors occur or can be created manually by creating a new instance of an exception class and throwing that exception.

As an example, consider the case of detecting when a divide by zero error occurs. Look at the divide method in the Interactions class. This method takes two int's, x and y, and returns x/y. What happens if y is 0? In this case, Java throws an ArithmeticException that represents the error. We use a try-catch to handle the occurrence of this error in a smooth way. The format of a try-catch is as follows:

try {
// some code that could result in an exception being thrown
} catch (ExceptionType1 e) {
// handle exceptions of Type1
} catch (ExceptionType2 e) {
// handle exceptions of Type2
}

There is one try-block, which contains code that can possibly create an exception. This is followed by one or more catch-blocks, each of which deals with a specific type of exception. In the case of the divide method there is only one type of exception we are interested in, so we have only one catch-block.

Try running the project and executing the divide method with different values for x and y. What happens when you enter 0 for y?

Manually Creating and Throwing Exceptions

You can manually create and throw an exception when an abnormal situation occurs. In this case, what situations are abnormal are defined by the programmer. For example, we may only want to allow our program to work with int's less than 1000. See the multiply method in the Interactions class. This method takes two int's, x and y, and returns x*y. If x*y > 1000 an exception is created and immediately caught. Try running this method with various inputs and observe the results.

Defining a Method to Throw Exceptions

In the case of multiply, we created and immediately caught an exception. Sometimes we may not know how to immediately handle the exception and want to pass the exception back to where the method was called and handle the error there. We define methods to throw errors in the following way:

void foo(...) throws ExceptionType1, ExceptionType 2 {
// some code that can throw ExceptionType1 and ExceptionType2
}

Any method that calls foo should place that call of foo in a try-catch block to handle the error or should itself be declared to throw those exceptions to a higher level.

As an example, see multiplyAndThrow in Interactions. This method is similar to multiply but the exceptions are not immediately handled. Try running this method and causing an exception to be thrown. Notice that the exception is printed to the console in red. This signifies that the exception was never caught and was reported by Java as a fatal error.

The method multiplyAndCatch calls multiplyAndThrow and handles the exceptions that it can throw with a try-catch statement.

Exercise: Add the methods subtractAndThrow and subtractAndCatch to the Interactions class. These methods should be similar to subtractAndThrow and subtractAndCatch described above.  Given two int's, x and y, they should return x-y and should produce an error if the result is negative.

Further Reading on Exceptions: Java tutorial on Handling Errors with Exceptions


Activity 3: Using Collections

The Collection interface is the root of a hierarchy of interfaces that represent groups of objects. There are three main types of  collections, each with a corresponding interface:

  1. List - an ordered collection of objects. Each object in a list has a specific position in the list. Lists can contain multiple occurrences of the same object. The lists you have been designing and using so far are all examples of this kind of collection. We will use only list collections in this lab, but you will use other types of collections in the coming labs.
  2. Set - an unordered collection of objects that can not contain duplicates. The set collections correspond closely to the mathematical notion of sets.
  3. Map - an unordered collection that relates keys to values. An example of this type of data is a dictionary. The words in the dictionary are keys that are mapped to their definitions, the values.
The LinkedList Class

 Find the LinkedList class in the Java API. We will use this list class as the basis of two new classes, Stack and Queue. A basic definition of these classes is provided for you. Each of them has one field, list, which is a LinkedList. Use this list as the basis for the stack and queue. Specifically, look at the following methods in the LinkedList class: addFirst, addLast, getFirst, getLast, removeFirst, removeLast, and size.

Exercise: Define Stack Methods

A stack is a last-in-first-out (LIFO) data structure. That is, the last element to be placed in the stack is the first one to be removed from it. An example is a stack of plates. Define the following four methods in the stack class. In the process of designing and implementing these methods you should define examples of stacks and test the methods. As an example, see the testStack method in the Examples class.

Methods to add to Stack:

  1. push: add the given Object to the top of the stack
  2. pop: return the Object at the top of the stack and remove it from the stack
  3. peek: return the Object at the top of the stack without removing it
  4. empty: return true if the stack is empty, return false otherwise
Exercise: Define Queue Methods

A queue is a first-in-first-out (FIFO) data structure. The first element placed in the queue will the first one to be taken out. An example is a line at the bank.

Design, implement, and test the following methods for the Queue class:

  1. enqueue: add the given Object to the back of the queue
  2. dequeue: return the Object at the front of the queue and remove it from the queue
  3. peek: return the Object front of the queue without removing it
  4. empty: return true if the queue is empty, return false otherwise
Further Reading on Collections: Java tutorial on Collections