Title: Exceptions
Course: CPS 261: Advanced Java Concepts ~ DL & MM MASTER

Exceptions

If you want to cover the same material from some other readings:

- Sun Certified Programmer for Java 2: Chapter 5: Exceptions chapter
- Thinking in Java (B Eckels book) Chapter 9: Error Handling with exceptions.
- Java Tutorial: Essential Classes : Handling Errors with Exceptions
- JDK: java.lang:  Throwable class

1. Basic Concept of Exceptions: - Exception handling allows developers to detect errors easily without writing special code to test return values. Traditional programming requires us to check return calls on every method we call and take some action when an error occurs. In a large system, this can generate some difficult to follow and hard to test programs. To see how the Exception error handling approach works, we need some definitons:
2. Exception - A class that is created at the point an error occurs. The Exception class contains detailed error information about what happens.
3. throwing an Exception - When an Exception occurs, the program that discovers the problem executes a statement that looks like:
Exception  e= new Exception("The xyz widget received an error 123 when accessing the abc method");
throw e;
4. Exception Processing - The code which is responsible for doing something about the error is called an exception handler, and it catches the exception. Exception handling works by trnasferring the execution of a program to an exception handler when an exception occurs.


try
{
  Your main line code
 }
 catch (Exception e)
 {
    Error Handling code
 }


5. More Specific Exception Processing

class IoCopy
{
    boolean byteCopy(String from, String to)
    {
        boolean retval = true;
        FileInputStream in =null ;
        FileOutputStream out =null;

        try
        {
            int b;
            in = new FileInputStream(from);
            out = new FileOutputStream(to);

            while ((b = in.read()) != -1)
                out.write(b);

            in.close();
            out.close()
        }
        catch (Exception e)
        {
            // Any I/O error sends us to this code.
	    // For example, if the "from" file doesn't exist,
	    // we will end up here.
            System.out.println("local Catch : " + e);
            retval = false;
        }
        return retval;
    }
    public static void main(String[] args)
    {
        IoCopy io = new IoCopy();
        io.byteCopy(args[0], "junk");
    }
}


For I/O processing, you can also "duck" the Exception try ... catch logic by "ducking" the issue. This is done by adding the following phrase after the method definition:
throws Exception
This is precisely what was done when we first covered I/O in the following example from the I/O Starter Notes
Note that the compiler forces you to do something with the potential Exceptions shown above. Try to eliminate the Exception handling logic and you will get a Compilation Error.
6. Throwable class - the parent class of all exceptions is in the java.lang package and is called Throwable. Throwable is derived from (you guessed it) Object.
  - The Throwable class has useful methods (see the Throwable class in package java.lang for details):
    - getMessage - returns information stored in the Throwable class
    - printStackTrace - prints out a list of all of the routines in the program calling stack.
  - Classes Derived from Throwable
    - Error - If you get an Error exception, there isn't much you can do. In this case the Java Run Time system is either crashed or out of resources. I'm not sure I have every generated Error Exceptions.
    - Exception - Most of your exceptions will be derived from the Exception class. Unless your class is derived from RuntimeException, the compiler will force you to deal with any exception that can be thrown.
7. Children of Exception - There are many classes derived from Exception. In fact there is a large tree of classes derived from Exception. Take a look at the Exception tree of classes in Online help . There is one significant subtree worth mentioning:
RuntimeException - RuntimeException is derived from Exception. All RuntimeExceptions and all classes derived from RuntimeExceptions have a unique property. Java does not force you to deal with RuntimeExceptions. This means that try ... catch logic is optional for RuntimeExceptions.
NON RuntimeException - Java forces you to deal with all Exceptions that are not part of the RuntimeException subtree. This means that either you surround the logic which can generate the exception with try ... catch logic or you "duck" the exception issue by adding to your method definition:
throws xyzException
"ducking" ramafications - If a method "ducks" an exception, then it's up to the calling method to process the exception. Of course the calling method can also "duck" an exception the same way used by the original method. If the main method "ducks" the exception, then the program aborts and the java program itself prints out the exception. You have probably already hit this case already by mistake.
8. Simple Example - This example shows a simple usage of Exceptions. All of the Exceptions in the following example are Derived from RuntimeException. This implies that handling these Exceptions is optional and not forced by the compiler. Compile this program and try the following executions of this program and explain the outcome:
  1. java SimpleExample 0 9
  2. java SimpleExample 0 0
  3. java SimpleExample
  4. java SimpleExample 11 1
  5. java SimpleExample 0 a


  class SimpleExample {
  static int compute(int a, int b) {
      int c;
      try
      {
        // Of b == 0, we will get an ArithmeticException
        c= a/b;
      }
      catch ( ArithmeticException e)
      {
         System.out.println(" Probably a divide by 0 case");
         c=0;
      }
      return c;
  }
  public static void main(String[] args) {
    int [] arr = new int[10];

    // Exceptions occur if we don't have enough parameters
    // We also get an Exception from parseInt if it a NON number
    int index = Integer.parseInt(args[0]);
    int i = Integer.parseInt(args[1]);

    int c = compute(10, i);

    // We can get an exception if index >= 10
    arr[index] = c;

    System.out.println(" Finished Simple Example");
  }
}


9. FixedExample - Now try the same executions as above except that the new program is called FixedExample instead of SimpleExample

  class FixedExample {
  static int compute(int a, int b) {
      int c;
     try
     {
       // An exception occurs if b == 0
       c= a/b;
     }
     catch ( ArithmeticException e)
     {
        System.out.println(" Probably a divide by 0 case");
        c=0;
     }
     return c;
  }
  public static void main(String[] args) {
    int [] arr = new int[10];

   try
      {
      // An exception will occur if we don't pass parameters
      // to this program, or the data passed is not something other
      // than a number.

       int index = Integer.parseInt(args[0]);

       int i = Integer.parseInt(args[1]);
       int c = compute(10, i);

       // if index >= 10 we get an exception
       arr[index] = c;
       }
   catch (NumberFormatException e)
       {
           System.out.println(" A non-numeric input parameter");
           e.printStackTrace();
       }
   catch (ArrayIndexOutOfBoundsException e)
       {
           System.out.println(" Array Index must be < 10");
           e.printStackTrace();
       }

   System.out.println(" Finished Simple Example");
  }
}


10. Note the use of printStackTrace. This useful function is expecially helpful in cases where the Exception can come from many different places
11. There are many styles for handling Exceptions. One last solution demonstrates handling all errors at the calling routine (main). It also demonstrates that catch clauses are processed in order until an Exception class match occurs. However, you can have a more generic class that catches all possibilities not already enumerated. The more generic class should be at the end of the list. The java compiler will give you a compilation errror if you get this backwards (i.e. more generic class before the more specific class). See the following example:

 class FixedExample2 {
 static void assign(int [] arr, int index, int a, int b)
  // The following line is optional because we are dealing
  // with RuntimeExceptions
 throws ArithmeticException, ArrayIndexOutOfBoundsException
  {
     // "ducking all Exceptions and passing it off to the caller
     arr[index] = a/b;
  }
  public static void main(String[] args) {
    int [] arr = new int[10];
    int index;

    try
       {
        index = Integer.parseInt(args[0]);
        int i = Integer.parseInt(args[1]);
        assign(arr, index, 10, i);
        }
    catch (NumberFormatException e)
        {
            System.out.println(" A non-numeric input parameter");
        }
    // The following will catch all Exceptions derived from RuntimeException that
    // haven't already been matched (i.e. NumberFormatException)
    catch (RuntimeException e)
        {
            System.out.println(" Some Runtime Exception: " +e);
            e.printStackTrace();
        }

    System.out.println(" Finished Simple Example");
  }
}


12. Here is another set of possibilities for the copy routine: All of the I/O exceptions must be handled because they aren't derived from RuntimeException. Analyze what happens with the following calls:
java Io1 1 Io1.java junk.txt
java Io1 1 Io1.java
java Io1 2 nonExistentFile junk.txt
java Io1 3 Io1.java
java Io1 3 nonExistentFile junk.txt

import java.io.*;

public class Io1 {

    // byteCopy "ducks" or "passes the buck" on Exceptions
    static void byteCopy(String from, String to) throws IOException
    {
        int b;
        FileInputStream in = new FileInputStream(from);
        FileOutputStream out = new FileOutputStream(to);

        while ((b = in.read()) != -1)
           out.write(b);

        in.close();
        out.close();
    }

    public static void main(String[] args) throws IOException {
        int value;

        // Possible Runtime Exception: NumberFormatException
        value = Integer.parseInt(args[0]);

        switch(value)
        {
        case 1:
          // main is ducking all exceptions here ---
          // so our program aborts when exceptions occur
          byteCopy(args[1], args[2]);
          break;

        case 2:
            // main is using Generic Exception Handling
            // in calling byteCopy routine.
            try
            {
                byteCopy(args[1], args[2]);
            }
            catch (Exception e)
            {
                System.out.println("I Caught It: " + e);
                e.printStackTrace();
            }
            break;

        case 3:
            // main is using more Specific Exception Handling
            // in calling byteCopy routine. We get more definitive
            // errors and this can allow us to take different actions
            // for different errors.

            try
            {
                byteCopy(args[1], args[2]);
            }

            catch (ArrayIndexOutOfBoundsException e)
            {
                System.out.println("I caught OutOfBounds " + e);
                e.printStackTrace();
            }

            catch (FileNotFoundException e)
            {
                System.out.println("I caught FileNotFound: " + e);
                e.printStackTrace();
            }
            // The more generic Exception handlers need to be at
            // the end of the list
            catch (Exception e)
            {
                System.out.println("I Caught It: " + e);
                e.printStackTrace();
            }
            break;

        }

    }
}




13. finally clause and More Local Exception Handling - Here is one more example where the exception handling is done in the routine which where the Exception actually gets thrown. Note that a finally clause can be used to provide code that executes after a successful try block or any catch clause. This gives you one place to provide cleanup code.

import java.io.*;

public class Io {
    // This version of byteCopy2 is proactive in handling Exceptions.
    // It does a good enough job that the calling routine doesn't need
    // to even know that byteCopy2 receives any Exceptions.

    static boolean byteCopy2(String from, String to)
    {
        boolean retval = true;
        FileInputStream in =null ;
        FileOutputStream out =null;

        try
        {
            int b;
            in = new FileInputStream(from);
            out = new FileOutputStream(to);

            while ((b = in.read()) != -1)
                out.write(b);
        }
        catch (FileNotFoundException e)
        {
            System.out.println("local FileNotFound Catch : " + e);
            retval = false;
        }
        catch (Exception e)
        {
            System.out.println("local Catch : " + e);
            retval = false;
        }
        finally
        {
           // The following try -- catch logic is forced on us
           // by the compiler because close can throw exceptions.
            try
            {
                if (in != null)in.close();
                if (out != null) out.close();
            }
            catch (Exception e)
            {
                System.out.println("Exception on closing file: " + e);
            }
        }
        return retval;
    }

    // This version of byteCopy3 is a hybrid example.  The most likely
    // I/O exception is handled locally.  The less likely Exceptions are
    // "ducked" and we allow main to deal with them.

    static void byteCopy3(String from, String to) throws IOException
    {
        FileInputStream in =null ;
        FileOutputStream out =null;
        int b;

        try
        {
            in = new FileInputStream(from);
        }
        catch (FileNotFoundException e)
        {
            System.out.println("local FileNotFound Catch : " + e);
            return;
        }

        out = new FileOutputStream(to);

        while ((b = in.read()) != -1)
                out.write(b);

        if (in != null)in.close();
        if (out != null) out.close();
    }

    public static void main(String[] args) throws IOException {
        int value;

        // Possible Runtime Exception: NumberFormatException
        value = Integer.parseInt(args[0]);

        switch(value)
        {
        case 4:
            // Check For Possible errors a little more locally
            // No indication that byteCopy2 even sees Exceptions.

            if (args.length >= 3)
            {
                if ( byteCopy2(args[1], args[2]))
                    System.out.println("Good Copy");
                 else
                    System.out.println("Bad Copy");
            }
            break;
        case 5:
            // A mixture of Local catching and global catching

            try
            {
                byteCopy3(args[1], args[2]);
            }
            catch (Exception e)
            {
                System.out.println("Caught in main: " + e);
            }
            break;
        }
    }// end of main
} // end of Io2 class




14. Overriding methods that throw Exceptions - The derived class can't throw exceptions that are not included in the list of classes thrown by the base class.


 public class MyBaseClass {
    public void myMethod() throws java.io.IOException { }
 }

 class OkSubClass0 extends MyBaseClass {
 // OK: Derived class throws the same as the base class
     public void myMethod() throws java.io.IOException {}
  }

  class OkSubClass1 extends MyBaseClass {
    // OK: Derived class throws Exception derived from the
    // Exception thrown by base class
    public void myMethod() throws java.io.FileNotFoundException {}
 }

 class OkSubClass2 extends MyBaseClass {
    //OK: Derived class doesn't need to throw exceptions
    // even if base class throws exceptions
    public void myMethod() {}
 }

 class OkSubClass3 extends MyBaseClass {
 // OK: All of these Exceptions are derived from IOException
 // which is the Exception thrown by the base class
    public void myMethod() throws java.io.EOFException,
       java.io.FileNotFoundException, java.util.zip.ZipException {}
 }

 class NotOkSubClass extends MyBaseClass {
    // NOT OK: AWTException not derived from IOException
    public void myMethod() throws java.awt.AWTException {} //Illegal
 }


15. Throwing exceptions - You can throw any exception that is defined with a command like:
throw new Exception("I found an error");
OR
throw new FileNotFoundException("Couldn't find my favorite file");
Here is a sample program that throws an exception that is nested in several calls of routines. The actual exception gets caught in the main routine.

  public class ExceptionMethods {
  static void firstLevel() throws Exception
  {
      secondLevel();
  }
  static void secondLevel() throws Exception
  {
      thirdLevel();
  }
  static void thirdLevel() throws Exception
  {
      throw new Exception("Here's my Exception");
  }

  public static void main(String[] args) {
    try {
      firstLevel();
    }
    catch(Exception e) {
      System.out.println("caught:" + e);
      e.printStackTrace();
    }
  }
}


16. Rethrowing an Exception - An exception handler can decide to rethrow an exception that it is currently processing:

  public class Rethrowing {
  public static void f() throws Exception {
    System.out.println("f() -- throw exception");
    throw new Exception("thrown from f()");
  }
  public static void g() throws Throwable {
    try
    {
      f();
    }
    catch(Exception e) {
      System.out.println("g() -- stack dump");
      e.printStackTrace();
      System.out.println("rethrowing Exception in g");
      throw e;
    }
  }
  public static void
  main(String[] args) throws Throwable {
    try {
      g();
    }
    catch(Exception e) {
      System.out.println("Caught in main" + e);
      e.printStackTrace();
    }
  }
}



Extra Examples
The following examples are optional
17. ShowDocument.java contains the source for an Applet that has browser capabilities. The main new classes covered here are the URL class and the AppletContext class. URL merely encapsulates the notion of a web URL. The AppletContext class has a member function called showDocument which will navigate your browser to a desired URL. Note there are 2 overloaded versions of showDocument. One of them allows the browser to determine which window to put the web page in. The other lets you target where you want your web page to go to (the target window). You also can put messages in the web browser status window with a showStatus call. This shows up best when you set the URL target to My Personal Window. By the way, this is the technique I use on my web site java navigator applet.
Note this example needs JDK1.1.x because I.E. only supports the older release ---- see Setup/Startup for setting up a JDK1.1.8 environment
showDocument.java


  /*
 * 1.1 version.
 */

import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.net.URL;
import java.net.MalformedURLException;

public class ShowDocument extends Applet
                          implements ActionListener {
    TextField urlField;
    Choice choice;


    public void init() {

    setLayout(new GridLayout(0,1));

    Label label1 = new Label("URL of document to show:",
                                 Label.LEFT);
    add(label1);

    urlField = new TextField("http://java.sun.com/", 50);
    urlField.addActionListener(this);
    add(urlField);

    Label label2 = new Label("Window/frame to show it in:",
                                 Label.LEFT);
    add(label2);

    choice = new Choice();
    choice.addItem("(browser's choice)"); //don't specify
    choice.addItem("My Personal Window"); //a window named
                                        //"My Personal Window"
    choice.addItem("_blank"); //a new, unnamed window
    choice.addItem("_self");
    choice.addItem("_parent");
    choice.addItem("_top"); //the Frame that contained this applet
    add(choice);

    Button button = new Button("Show document");
    button.addActionListener(this);
    add(button);

    }

    public void actionPerformed(ActionEvent event) {
       String urlString = urlField.getText();
       URL url = null;
       AppletContext context;
       context = getAppletContext();

       try {
            url = new URL(urlString);
            context.showStatus("Mine: "+urlString);
            if (url != null) {
               if (choice.getSelectedIndex() == 0)
                   context.showDocument(url);
               else
                   context.showDocument(url,
                                  choice.getSelectedItem());
               }
           }
        catch (MalformedURLException e)
           {
               System.err.println("Malformed URL: " + urlString);
           }
    }
}



showDocument.html

<html><body>
<applet code=ShowDocument width=500 height=200>
</applet>


</body></html>



Uncaught Exception Example

ThrowOut.java
The main routine catch routine does not catch the thrown exception because the catch routine isn't catching a "large enough" class.


 //: ThrowOut.java
public class ThrowOut {
  public static void
  main(String[] args) throws Throwable {
    try {
      throw new Throwable();
    } catch(Exception e) {
    // Not caught because Throwable is " > " Exception
      System.out.println("Caught in main()");
    }
  }
}




Exception Matching

Human.java
In this example, the first catch which contains the thrown exception will be used. Note that if you comment out the first catch phrase, the second catch phrase will then be used.


 //: Human.java
// Catching Exception Hierarchies

class Annoyance extends Exception {}
class Sneeze extends Annoyance {}

public class Human {
  public static void main(String[] args) {
    try {
      throw new Sneeze();
    } catch(Sneeze s) {
      System.out.println("Caught Sneeze");
    } catch(Annoyance a) {
      System.out.println("Caught Annoyance");
    }
  }
}




Throwing a RuntimeException

NeverCaught.java
The compiler doesn't force us to catch RuntimeExceptions Consequently, we never had to add the Throws clause on our procedure definitions. Because nothing catches this specific RuntimeException, it gets caught in the Run Time System Virtual Machine.


 //: NeverCaught.java
// Ignoring RuntimeExceptions

public class NeverCaught {
  static void f() {
    throw new RuntimeException("From f()");
  }
  static void g() {
    f();
  }
  public static void main(String[] args) {
    g();
  }
}




Creating Your Own Exception

Inheriting.java
In this example we create our own Exception class derived from Exception.


 //: Inheriting.java
// Inheriting your own exceptions

class MyException extends Exception {
  public MyException() {}
  public MyException(String msg) {
    super(msg);
  }
}

public class Inheriting {
  public static void g() throws MyException {
    System.out.println(
      "Throwing MyException from g()");
    throw new MyException("Originated in g()");
  }
  public static void main(String[] args) {

    try {
      g();
    } catch(MyException e) {
      System.out.println("getMessage = "+
              e.getMessage());
      e.printStackTrace();
    }
  }
}



Another Example of creating a new Exception class: Multiple constructors

Inheriting2.java
In this example we create our own Exception class derived from Exception. Sometimes its handy to have multiple constructors. Note also that we are overriding the getMessage routine. This is also handy.


 //: Inheriting2.java
// Inheriting your own exceptions

class MyException2 extends Exception {
  public MyException2() {}
  public MyException2(String msg) {
    super(msg);
  }
  public MyException2(String msg, int x) {
    super(msg);
    i = x;
  }
  public int val() { return i; }
  public String getMessage()
  {
      String str = super.getMessage();
      str += " Integer = " + i;
      return str;
  }
  private int i=-1;
}

public class Inheriting2 {
  public static void f() throws MyException2 {
    System.out.println(
      "Throwing MyException2 from f()");
    throw new MyException2();
  }
  public static void g() throws MyException2 {
    System.out.println(
      "Throwing MyException2 from g()");
    throw new MyException2("Originated in g()");
  }
  public static void h() throws MyException2 {
    System.out.println(
      "Throwing MyException2 from h()");
    throw new MyException2(
      "Originated in h()", 47);
  }
  public static void main(String[] args) {
    try {
      f();
    } catch(MyException2 e) {
        System.out.println("getMessage = "+
              e.getMessage());

          e.printStackTrace();
    }
    try {
      g();
    } catch(MyException2 e) {
        System.out.println("getMessage = "+
              e.getMessage());
          e.printStackTrace();
    }
    try {
      h();
    } catch(MyException2 e) {
        System.out.println("getMessage = "+
              e.getMessage());
          e.printStackTrace();
          System.out.println("e.val() = " + e.val());
    }
  }
}

Exercises:

Last Updated: October 8, 2003 12:56 PM