Programming Tutorials Browser Tutorials Articles Struts Tutorials Hibernate Tutorials

  Tutorial: Designing with exceptions - JavaWorld - July 1998

Designing with exceptions - JavaWorld - July 1998

Tutorial Details:

Designing with exceptions
Designing with exceptions
By: By Bill Venners
Guidelines and tips on when and how to use exceptions
ive months ago, I began a mini-series of articles about designing objects. In this Design Techniques article, I'll continue that series by looking at design principles that concern error reporting and exceptions. I'll assume in this article that you know what exceptions are and how they work. If you would like a refresher on exceptions in general, see the companion article, "Exceptions in Java" .
The benefits of exceptions
Exceptions have several benefits. First, they allow you to separate error handling code from normal code. You can surround the code that you expect to execute 99.9% of the time with a try block, and then place error handling code in catch clauses -- code that you don't expect to get executed often, if ever. This arrangement has the nice benefit of making your "normal" code less cluttered.
If you feel that a method doesn't know how to handle a particular error, you can throw an exception from the method and let someone else deal with it. If you throw a "checked" exception, you enlist the help of the Java compiler to force client programmers to deal with the potential exception, either by catching it or declaring it in the throws clause of their methods. The fact that Java compilers make sure checked exceptions are handled helps make Java programs more robust.
When to throw exceptions
When should you throw an exception? The answer can be summed up in one guideline:
If your method encounters an abnormal condition that it can't handle, it should throw an exception.
Unfortunately, though this guideline may be easy to memorize and may sound impressive when you recite it at parties, it doesn't clear up the picture too much. It actually leads to a different question: What is an "abnormal condition?"
That, it turns out, is the $64,000 question. Deciding whether or not a particular event qualifies as an "abnormal condition" is a subjective judgment. The decision is not always obvious. It's one reason they pay you the big bucks.
A more helpful rule of thumb could be:
Avoid using exceptions to indicate conditions that can reasonably be expected as part of the typical functioning of the method.
An abnormal condition, therefore, would be any condition that wouldn't reasonably be expected as part of the "normal functioning" of a method. To help you get a feel for what I mean by "normal functioning of a method," allow me to give a few examples.
A few examples
As an illustration, consider the FileInputStream and DataInputStream classes from the java.io package. Here is an application that uses FileInputStream to print the text of a file to the standard output:
// In source packet in file except/ex9/Example9a.java
import java.io.*;
class Example9a {
public static void main(String[] args)
throws IOException {
if (args.length == 0) {
System.out.println("Must give filename as first arg.");
return;
}
FileInputStream in;
try {
in = new FileInputStream(args[0]);
}
catch (FileNotFoundException e) {
System.out.println("Can't find file: " + args[0]);
return;
}
int ch;
while ((ch = in.read()) != -1) {
System.out.print((char) ch);
}
System.out.println();
in.close();
}
}
This example shows that the read() method of FileInputStream reports an "end of file has been reached" condition not by throwing an exception, but by returning a special value: -1. In this method, reaching end of file is considered a "normal" part of using the method. It is not considered an "abnormal" condition. The usual way to read bytes is to keep on reading them until you hit the end.
The DataInputStream class, on the other hand, takes a different approach when reporting end of file:
// In source packet in file except/ex9b/Example9b.java
import java.io.*;
class Example9b {
public static void main(String[] args)
throws IOException {
if (args.length == 0) {
System.out.println("Must give filename as first arg.");
return;
}
FileInputStream fin;
try {
fin = new FileInputStream(args[0]);
}
catch (FileNotFoundException e) {
System.out.println("Can't find file: " + args[0]);
return;
}
DataInputStream din = new DataInputStream(fin);
try {
int i;
for (;;) {
i = din.readInt();
System.out.println(i);
}
}
catch (EOFException e) {
}
fin.close();
}
}
Each time the readInt() method of DataInputStream is invoked, it reads four bytes from the stream and interprets them as an int . When readInt() encounters end of file, it throws EOFException .
Throwing an exception is a reasonable approach for this method for two reasons. First, readInt() can't return a special value to indicate end of file, because all possible return values are valid int s. (It can't return -1 on end of file, for example, because it may read a -1 from the stream and need to return it as a valid int value.) Second, if readInt() encounters end of file after reading only one, two, or three bytes, that probably qualifies as an "abnormal condition." The method is supposed to read four bytes, but only one to three are available. Given that this exception is an integral part of using this class, it is a checked exception (a subclass of Exception ). Client programmers are forced to deal with it.
A third approach to signaling an "end has been reached" condition is illustrated by the StringTokenizer and Stack classes in the following example:
// In source packet in file except/ex9b/Example9c.java
// This program prints the white-space separated tokens of an
// ASCII file in reverse order of their appearance in the file.
import java.io.*;
import java.util.*;
class Example9c {
public static void main(String[] args)
throws IOException {
if (args.length == 0) {
System.out.println("Must give filename as first arg.");
return;
}
FileInputStream in = null;
try {
in = new FileInputStream(args[0]);
}
catch (FileNotFoundException e) {
System.out.println("Can't find file: " + args[0]);
return;
}
// Read file into a StringBuffer
StringBuffer buf = new StringBuffer();
try {
int ch;
while ((ch = in.read()) != -1) {
buf.append((char) ch);
}
}
finally {
in.close();
}
// Separate StringBuffer into tokens and
// push each token into a Stack
StringTokenizer tok = new StringTokenizer(buf.toString());
Stack stack = new Stack();
while (tok.hasMoreTokens()) {
stack.push(tok.nextToken());
}
// Print out tokens in reverse order.
while (!stack.empty()) {
System.out.println((String) stack.pop());
}
}
}
This example reads in the bytes of a file, converts them to char s, and places the char s into a StringBuffer . It then uses a StringTokenizer to extract one white-space separated token (a String ) at a time and push it onto a Stack . Next it pops all tokens from the Stack and prints them out one per line. Because Stack implements a Last In First Out (LIFO) stack, the tokens are printed in reverse order from their appearance in the file.
Both the StringTokenizer and the Stack must signal an "end has been reached" condition. The StringTokenizer constructor takes as a parameter the source String to tokenize. Each invocation of nextToken() returns a String that represents the next token of the source String . Eventually, all the tokens in the source String will be consumed, and StringTokenizer must somehow indicate that the end of tokens has been reached. In this case, there is a special return value, null , that could have been used to indicate the end of tokens. But the designer of this class took a different approach. A separate method, hasMoreTokens() , returns a boolean value indicating whether or not the end of tokens has been reached. You must invoke hasMoreTokens() each time you invoke nextToken() .
This approach shows that the designer did not consider reaching the end of tokens an abnormal condition. It is a normal way to use the class. After the end has been reached, however, if you don't check hasMoreTokens() and call nextToken() , you will be rewarded with the NoSuchElementException . Although this exception is thrown on an end of tokens condition, it is an unchecked exception (a subclass of RuntimeException ). It is thrown more to indicate a software bug -- that you are not using the class correctly -- than to indicate the end of tokens condition.
Similarly, the Stack class has a method, empty() , that returns a boolean to indicate that the last object has been popped from the stack. You must invoke empty() each time you invoke pop() . If you neglect to invoke empty() and invoke pop() on an empty stack, you get an EmptyStackException . Although this exception is thrown when an "end of objects on the stack" condition is encountered, it is another unchecked runtime exception. It is intended to be more an indication of a software bug in the client code (the improper use of the Stack class) than the normal way to detect an empty stack.
Exceptions indicate a broken contract
The examples above should give you a feel for when you would want to throw an exception instead of using some other means to communicate an event. One other way to think about exceptions, which may give you more insight into when you should use them, is that exceptions indicate a "broken contract."
One design approach often discussed in the context of object-oriented programming is the Design by Contract approach. This approach to software design says that a method represents a contract between the client (the caller of the method) and the class that declares the method. The contract includes preconditions that the client must fulfill and postconditions that the method itself must fulfill.
Precondition
One example of a method with a precondition is the charAt(int index) method of class String . This method requires that the index parameter passed by the client be between 0 and one less than the value returned by invoking length() on the String object. In other words, if the length of a String is 5, the index p


 

Read Tutorial at: Click here to view the tutorial

Rate Tutorial:
Designing with exceptions - JavaWorld - July 1998

View Tutorial:
Designing with exceptions - JavaWorld - July 1998

Related Tutorials:

Enhance your Java application with Java Native Interface (JNI)
Enhance your Java application with Java Native Interface (JNI)
 
Sir, what is your preference?
Sir, what is your preference?
 
Implement Design by Contract for Java using dynamic proxies
Implement Design by Contract for Java using dynamic proxies
 
Exceptions: Don't get thrown for a loss
Exceptions: Don't get thrown for a loss
 
Beware the dangers of generic Exceptions
Beware the dangers of generic Exceptions
 
Practical Reflection: an excerpt from Hardcore Java
Practical Reflection: an excerpt from Hardcore Java In this chapter from Hardcore Java, "Practical Reflection," Robert Simmons Jr. writes: "Reflection is one of the least understood aspects of Java, but also one of the most powerful. Reflection is used i
 
Java Development on Eclipse, Part 2
Java Development on Eclipse, Part 2 Editor's note: In part one of this two-part series of excerpts from Eclipse, author Steve Holzner provided examples of how Eclipse makes it easier to create Java code from scratch. Continuing in that vein, in this we
 
Java theory and practice: Kill bugs dead
Inspection tools like FindBugs provide a second layer of defense against common coding errors.
 
Designing J2EE Applications for Real-Life Clustered Environments
Designing J2EE Applications for Real-Life Clustered Environments In this article, the authors draw from their practical experience to list and discuss some critical considerations when building J2EE applications so that they can be deployed in a cluste
 
Attribute-Oriented Programming with Java 1.5, Part 2
Peeking Inside the Box: Attribute-Oriented Programming with Java 1.5,Part In the previous article in this series, "Peeking Inside the Box, Part 1," I introduced the concepts of Attribute-Oriented Programming, Java 1.5 annotations, and bytecode instrume
 
Java look and feel icons
These pages contain a collection of toolbar button graphics. The graphics have been designed specifically for use with the Java look and feel. They conform to the Java look and feel Design Guidelines (see the "Designing Button Graphics" section of the "Ap
 
Garbage Collection in the Java HotSpot Virtual Machine
Garbage Collection in the Java HotSpot Virtual Machine Gain a better understanding of how garbage collection in the Java HotSpot VM works, and learn to take full advantage of it when designing, developing, and deploying your Java applications.
 
Java Resources
There are all Java freebies. Some of these are old, and not under maintenance. Download and use them at your risk. In case of queries, mail subrahmanyam_avb@technologist.com or varalakshmi_a@techie.com.
 
JSPTags.com offers JSP developers a directory of resources.
JSPTags.com offers JSP developers a directory of resources related to JavaServer Pages, Servlets and Java. As the name JSPTags.com implies, special interest is given to JSP Tag Libraries. Many developers are working with and designing new JSP Tag Librarie
 
Advanced Features of JSP Custom Tag Libraries
In this article, the second in the JSP custom tag libraries series, we will cover advanced JSP features and how to use them.
 
Getting Started With Composite Capabilities/Preference Profiles and JSR 188
This article presents Composite Capabilities/Preference Profiles for designing content once. JSR 188 allows users to access the same application or content from any device, and be confident that it will work on that device, and will accommodate their pref
 
What package names are defined in the J2ME environment?
A compendium of J2ME package names, neatly arranged by JSR and presented for your illumination.
 
Struts, JavaServer Faces, and Java Studio Creator:
The Evolution of Web Application Frameworks Sun Microsystems' Craig McClanahan, the creator of the Apache Struts Framework, co-specification lead for JavaServer Faces 1.0, and prime architect for Sun Java Studio Creator's new release, explains all three.
 
Your homepage for Cheapest domain name registration, Domain Forwarding Services, Web Designing | Roseindia Domain Regist
Your homepage for Cheapest domain name registration, Domain Forwarding Services, Web Designing | Roseindia Domain Registration DOMAIN REGISTRATION SERVICES Roseindia.net is the leading provider of cheapest Domain registration services in India.
 
Parisonz Solutions!
Parisonz Solutions! W elcome to Parisonz Solutions . The purpose of this web is to Develop and Distribute Projects to Businesses and Individuals though Web. We have a wide range of projects completed online — including software development, web
 
Site navigation
 

 

Send your comments, Suggestions or Queries regarding this site at roseindia_net@yahoo.com.

Copyright © 2006. All rights reserved.