TOM
 
Why methods do not declare the exceptions they raise
 
 
TOM Home
TOM Tasks

FAQ
News
Highlights
Publications
Documentation
Download TOM
TOM Software
Bug Database
Mailing Lists

Mail:
tiggr at gerbil.org

Short Cuts:
Tesla
TOM/Gtk
GP
MU

Snapshots:
all of 'em
tom [an error occurred while processing this directive]
tesla [an error occurred while processing this directive]
mu [an error occurred while processing this directive]
tomgtk [an error occurred while processing this directive]

Released:
all of 'em
tom 1.1.1
tomgtk 0.11
tesla 0.91
gp 0.5
mu 1.0

Misc:
GIF free NOW!

Last week, I had my first hands-on Java experience. I had previously read a few of the Java related books to come out of Sun, so I know quite a lot about the language. But, as always, actually doing something can provide instant insights you didn't previously have. This one was related to exceptions.

I had always thought the Java thing of declaring which exceptions a method can throw to be a neat documentation trick, but how wrong was I!

I wanted to display a little graphic in an Applet and update it, say, every second. The Thread class delivers a sleep method so that seemed the method to be called. I had (still have) the impression that the sleep-and-redraw loop had to be done in a separate thread, so I made my class implement the Runnable interface, and wrote my little run method.

public class Clock extends Applet
  implements Runnable
{
  Canvas draw_thing;

  public static void main ...;

  public void
  run ()
  {
    for (;;)
      {
        Thread.currentThread ().sleep (1000);
        draw_thing.repaint ();
      }
  }
}
Bang! The compiler does not like it: the sleep method can throw an InterruptedException. I am not interested in this exception at all, let alone in catching it, but as a result I must annotate my run method to be throwing InterruptedExceptions. If that's all, I think, then that's fine. My previous impression that the exception annotation was a nice doc thingy had gotten its first dent.

The new run method's heading becomes

public void
run ()
throws InterruptedException
and again the compiler is not satisfied: the run method declared in the Runnable interface is not declared to throw anything, and so must my implementation of that method.

So, I am forced to adhere to the Runnable interface because I want to deliver a method (which must be the run method) that a new Thread can invoke. Because the interface dictates nothing about exceptions, my run method must catch any exception that any of the methods it invokes may raise.

What is it that my run method must do with the exception? It is not allowed to raise anything, so the best thing it can do is output some information regarding the situation, but followed by what? Should it continue execution as if nothing happened? That is a bad idea; the exception was not raised for nothing. Should it stop execution and return? In that case the calling method has no way of telling whether the method returned because it should or because it was forced to. And if my method did not return void, but, e.g., an int, like functions in C regularly do to express an error or the absence thereof, should I have returned an error? Should I let all my methods return some indication of success, just to be able to inform the caller? If so, what good are exceptions?

Concluding: having to declare exceptions with a method forces one into local error handling at inappropriate places. This is inferior when compared to total freedom, and contrary to what exceptions are meant for.


Some notes (Mon Mar 2 1998)

Apparantly, RuntimeException exceptions do not need to be declared (thank you Michael for pointing this out). Which only shows that the exception declaration concept is broken: `You must declare the exceptions that can be raised, except the ones that would need to be included in every method.' To paraphrase a famous quote: All exceptions are equal, except...

As an indication of the mis-use of exceptions given the restriction discussed in this highlight, let me quote a randomly chosen piece of code from the Code Examples for The Java Class Libraries: Second Edition, Volume 2 (from java/awt/Button/Main.java, reformatted):

public void run()
{
  while (timerThread == Thread.currentThread())
    {
      timeDisp.setText("" + time/10 + ":"
                       + time%10 + "0");
      time++;
      try { Thread.sleep(100); }
      catch (Exception e) {};
    }
}
QED.


More notes (Mon Sep 28 1998)

After actually reading what has been written on the subject of `exception specifications', I should add to the above remark that Java discerns checked and unchecked exceptions. The latter include RuntimeException and Error; the former include the rest. The point made in this highlight is not affected by this clarification.


Up: Highlights
 
Copyright © 1997-2002 Programmers Without Deadlines