Saturday, March 12, 2011

Runtime Exceptions--The Controversy

Because the Java language does not require methods to catch or specify runtime exceptions, it's tempting for programmers to write code that throws only runtime exceptions or to make all of their exception subclasses inherit from RuntimeException. Both of these programming shortcuts allow programmers to write Java code without bothering with all of the nagging errors from the compiler and without bothering to specify or catch any exceptions. While this may seem convenient to the programmer, it sidesteps the intent of Java's catch or specify requirement and can cause problems for the programmers using your classes.
InputFile.java:8: Warning: Exception
java.io.FileNotFoundException must be caught, or it must be
declared in throws clause of this method.
fis = new FileInputStream(filename);
^

Why did the Java designers decide to force a method to specify all uncaught checked exceptions that can be thrown within its scope? Because any exception that can be thrown by a method is really part of the method's public programming interface: callers of a method must know about the exceptions that a method can throw in order to intelligently and conciously decide what to do about those exceptions. The exceptions that a method can throw are as much a part of that method's programming interface as its parameters and return value.

Your next question might be: "Well then, if it's so good to document a method's API including the exceptions that it can throw, why not specify runtime exceptions, too?"

Runtime exceptions represent problems that are detected by the runtime system. This includes arithmetic exceptions (such as when dividing by zero), pointer exceptions (such as trying to access an object through a null reference), and indexing exceptions (such as attempting to access an array element through an index that is too large or too small).

Runtime exceptions can occur anywhere in a program and in a typical program can be very numerous. Typically, the cost of checking for runtime exceptions exceeds the benefit of catching or specifying them. Thus the compiler does not require that you catch or specify runtime exceptions, although you can.

Checked exceptions represent useful information about the operation of a legally specified request that the caller may have had no control over and that the caller needs to be informed about--for example, the file system is now full, or the remote end has closed the connection, or the access privileges don't allow this action.

What does it buy you if you throw a RuntimeException or create a subclass of RuntimeException just because you don't want to deal with specifying it? Simply, you get the ability to throw an exception without specifying that you do so. In other words, it is a way to avoid documenting the exceptions that a method can throw. When is this good? Well, when is it ever good to avoid documenting a method's behavior? The answer is "hardly ever."


Rules of Thumb:



  • A method can detect and throw a RuntimeException when it's encountered an error in the virtual machine runtime. However, it's typically easier to just let the virtual machine detect and throw it. Normally, the methods you write should throw Exceptions, not RuntimeException.

  • Similarly, you create a subclass of RuntimeException when you are creating an error in the virtual machine runtime (which you probably aren't). Otherwise you should subclass Exception.

  • Do not throw a runtime exception or create a subclass of RuntimeException simply because you don't want to be bothered with specifying the exceptions your methods can throw.

No comments:

Post a Comment

Chitika