CSCI 202 in-class lab — Exceptions

The goal

We’re going to try to cover a few of the topics in the Java lesson on exceptions during this lab.

Getting started

Create a ExceptionLab project for a Java application with a main class called ExceptionLab.

Within the class have one static method, myCall. It doesn’t particularly matter whan this methods does, but it should have one parameter, a String, and return a String. Also, have main call myCall and print its result.

If you can’t come up with anything better, try the following:

    private static String myCall(String s) {
        return "abcd" + s ;
    }
    
    public static void main(String[] args) {
        System.out.println(myCall("wxyz")) ;
    }

The three types of exceptions

There are three types of exceptions in Java.

Runtime exceptions

The first type is the runtime exception. The designers of Java believed that these or avoidable errors that would only result from poor programming. Java has a special class RuntimeException for these errors. Take a look at this class. You will see a few exceptions, such as IndexOutOfBoundExceptions and NullPointerException, that sometimes crop up in CSCI 202 and 333 programs.

Modify your myCall method so that it causes a RunTimeException. You can always just index outside the bounds of an array. We’ve all done that many times.

Error

The second type of exception is the error. These are for problems that are the fault of the system and not the program. Again Java has a special class Error for these exceptions. Oops, the Error is actually a subclass of Throwable not Exception, which is also a subclass of Throwable.

It’s a little hard to get an Error. You best bet would be to write a program that runs out of memory space. We’ll show you how to do this in lab.

Checked exceptions

And finally there is the checked exception. These are “exceptional conditions that a well-written application should anticipate and recover from.” The Java compiler considers any Exception that is not a RuntimeException to be a checked exception.

The Java compiler requires either a try-catch or a throws for every possible checked exception.

Add the following import statements to your Java program.

import java.util.Scanner ;
import java.io.* ;

Now replace the body of your myCall method with the following two statements.

        Scanner inStream = new Scanner(new File(s)) ;
        return inStream.nextLine() ;

Java will refuse to compile your program.

Relaying an exception

There’s a lot to be said for putting off hard work or, even better, passing it on to someone else. Add the words throws FileNotFoundException to the header of the myCall method. You’ll notice that Java is no longer complaining about a FileNotFoundException within myCall.

Unfortunately, the problem has now been passed to the main method. Of course, adding a throws FileNotFoundException to the main header solves that problem.

Add the two throws FileNotFoundException to the myCall and main methods. Now run your program. It will crash due to a unhandled checked exception. You should see a stack trace similar to the following:

Exception in thread "main" java.io.FileNotFoundException: lmno (The system cannot find the file specified)
at java.io.FileInputStream.open(Native Method)
at java.io.FileInputStream.<init>(FileInputStream.java:138)
    at java.util.Scanner.<init>(Scanner.java:656)
      at edu.unca.cs.csci202.LabException.myCall(LabException.java:14)
      at edu.unca.cs.csci202.LabException.main(LabException.java:33)
Java Result: 1

The last two lines indicate that myCall passed the FileNotFoundException up to main. Click on one of those file/line combinations, such as (LabException.java:14). This will take you to the line of code where the problem occured. This can be very useful when debugging programs.

It really was appropriate for myCall to just pass the FileNotFoundException up to main. After the responsibility for the problem does belond to main. However, in the remainder of the lab, we’re going to “fix” this problem mostly be modifying myCall.

Catching an exception

Using try and catch, let’s add an exception handler to myCall with a catch for any type of IOException.

For now have myCall return "" if an exception occues.

Remove the throws FileNotFoundException from your code. We’ll finish up this one together in the lab.

If you are running on one of the hard workstations, you can pass the string "/etc/passwd" to myCode to have in read a line and can passed "/etc/shadow" for the exception.

And finally

One of the shortcomings of our present solution is that the Scanner is not closed if an IOException occurs while reading the file. We need to all a finally block to the program that does this one.

Add the appropriate finally block that closes the Scanner object. You will need to place the declaration of the Scanner before the block to make this work. This offers a time to think about the role of scope in Java.

Try with resources

You can read about a new form of the try introduced in Java 7 that offers a better, but more complex, solution to this problem. This new feature of Java is not covered in the textbook and you will need to know a bit about interfaces to understand it.

Thowing an exception

Many times methods throw exception. In this case, we are going to change myCall to thow IOException when it is passed a String that isn’t the name of a readable file.

You will need to add throws IOException to both myCall and main. (Think about why main needs this.)

Then replace the body of the catch for IOException so that it throws an IOException with the message "Unable to read a line".

Creating your own exception

Although it’s really silly to create our own expection, let’s create one called LabIOException in the package edu.unca.cs.csci202.

Just follow along with some of the textbook’s note for Designing Your Own Exception Types.