Tips for Using Exceptions - Proper use of exceptions
1.
Exception handling is not supposed to replace a simple test.
As an
example of this, we wrote some code that tries 10,000,000 times to pop an empty
stack. It first does this by finding out whether the stack is empty.
if
(!s.empty()) s.pop();
Next,
we tell it to pop the stack no matter what. Then, we catch the EmptyStackException that tells us that we
should not have done that.
try()
{
s.pop();
}
catch
(EmptyStackException e)
{
}
Table
11–1 Timing Data Test Throw/Catch
646 milliseconds 21,739 milliseconds
Use
exceptions for exceptional circumstances only.
2. Do not micromanage
exceptions
Many
programmers wrap every statement in a separate try block.
OutputStream
out;
Stack
s;
for
(i = 0; i < 100; i++)
{
try
{
n
= s.pop();
}
catch
(EmptyStackException s)
{
//
stack was empty
}
try
{
out.writeInt(n);
}
catch
(IOException e)
{
//
problem writing to file
}
}
try
{
for
(i = 0; i < 100; i++)
{
n
= s.pop();
out.writeInt(n);
}
}
catch
(IOException e)
{
//
problem writing to file
}
catch
(EmptyStackException s)
{
//
stack was empty
}
This
code looks much cleaner. It fulfills one of the promises of exception handling,
to separate
normal
processing from error handling.
3.
Make good use of the exception hierarchy.
Don’t
just throw a RuntimeException. Find an appropriate subclass or create your own. Don’t
just catch Throwable. It makes your code
hard to read and maintain. Respect the difference between checked and unchecked
exceptions. For example, when you parse an integer in a file, catch the NumberFormatException and turn it into a
subclass of IOException
or MySubsystemException.
4. Do not squelch
(waste/kill) exceptions.
In
Java, there is the tremendous temptation to shut up exceptions.
public
Image loadImage(String s)
{
try
{
code
that threatens to throw checked exceptions
}
catch
(Exception e)
{}
// so there
}
Now
your code will compile without a hitch. It will run fine, except when an
exception occurs. Then, the exception will be silently ignored. If you believe
that exceptions are at all important, you should make some effort to handle
them right.
6. Propagating
exceptions is not a sign of shame.
Many
programmers feel compelled to catch all exceptions that are thrown. If they call
a method that throws an exception, such as the FileInputStream constructor or the readLine method, they
instinctively catch the exception that may be generated. Often, it is actually
better to propagate
(transmit) the exception instead
of catching it:
public
void readStuff(String filename) throws IOException // not a sign of shame!
{
InputStream
in = new FileInputStream(filename);
.
. .
}
Higher-level
methods are often better equipped to inform the user of errors or to
abandon
unsuccessful commands.
Assertions
Assertions are a
commonly used idiom for defensive programming. Suppose you are convinced that a
particular property is fulfilled, and you rely on that property in your code.
For example, you may
be computing
double y = Math.sqrt(x);
You are certain that x is not negative.
Perhaps it is the result of another computation that can’t have a negative
result, or it is a parameter of a method that requires its callers to supply
only positive inputs.
if (x < 0) throw
new IllegalArgumentException("x < 0");
But this code stays
in the program, even after testing is complete. If you have lots of checks of
this kind, the program runs quite a bit slower than it should.
The assertion
mechanism allows you to put in checks during testing and to have them automatically
removed in the production code.
- assertion
to test our assumption about programs. That means it validates our
program!
- assertions
ensures the program validity by catching exceptions and logical errors
assert condition;
and
assert condition : expression;
Both statements
evaluate the condition and throw an AssertionError if it is false. In the second
statement, the
expression is passed to the constructor of the AssertionError object and turned
into a message string.
To assert that x is nonnegative, you
can simply use the statement
assert x >= 0;
Or you can pass the
actual value of x into the AssertionError object, so that it
gets displayed
later.
assert x >= 0 : x;
Using Assertions for
Documenting Assumptions
Many programmers use
comments to document their underlying assumptions. Consider this example from
if (i % 3 == 0)
. . .
else if (i % 3 == 1)
. . .
else // (i % 3 == 2)
. . .
In this case, it
makes a lot of sense to use an assertion instead.
if (i % 3 == 0)
…………
else if (i % 3 == 1)
. . .
else
{
assert i % 3 == 2;
. . .
}
Better: assert
i<0;
import java.util.*;
import java.util.Scanner; public class AssertionExample { public static void main( String args[] ) { Scanner scanner = new Scanner( System.in ); System.out.print( "Enter a number between 0 and 20: " ); int value = scanner.nextInt(); assert( value >= 0 && value <= 20 ) : "Invalid number: " + value; System.out.printf( "You have entered %d\n", value ); } } |
To run the above example,
Compile the example with: javac AssertionExample.java
Run the example with: java -ea AssertionExample
To enable assertions at runtime, -ea command-line option is used
Compile the example with: javac AssertionExample.java
Run the example with: java -ea AssertionExample
To enable assertions at runtime, -ea command-line option is used
No comments:
Post a Comment