Sample Quiz Answers
For Chapter 9
THIS PAGE CONTAINS SAMPLE ANSWERS to the Quiz on
Chapter 9 of this on-line
Java textbook. Note that in many cases, there are lots of correct
answers to a given question.
Question 1:
What does it mean to say that a program is robust?
Answer:
A robust program is one that can handle errors and other unexpected
conditions in some reasonable way. This means that the program must
anticipate possible errors and respond to them if they occur.
Question 2:
Why do programming languages require that variables be declared before
they are used? What does this have to do with correctness and robustness?
Answer:
It's a little inconvenient to have to declare every variable before it
is used, but its much safer. If the compiler would accept undeclared
variables, then it would also accept misspelled names and treat them
as valid variables. This can easily lead to incorrect programs.
When variables must be declared, the unintentional creation of
a variable is simply impossible, and a whole class of possible
bugs is avoided.
Question 3:
What is "Double.NaN"?
Answer:
Double.NaN is a special value of type double. (It is
defined as a public static member variable of the
standard class, Double.) It is used to represent the result
of an undefined operation on real numbers. For example, if you
divide a number of type double by zero, the result will
be Double.NaN.
Question 4:
What is a precondition? Give an example.
Answer:
A precondition is a condition that has to hold at given point
in the execution of a program, if the execution of the program
is to continue correctly. For example, the
statement "x = A[i];" has two preconditions: that
A is not null and that 0 <= i < A.length.
If either of these preconditions is violated, then the execution
of the statement will generate an error.
Also, a precondition of a subroutine
is a condition that has to be true when the subroutine is called
in order for the subroutine to work correctly.
Question 5:
Explain how preconditions can be used as an aid in
writing correct programs.
Answer:
Suppose that a programmer recognizes a precondition at some point in
a program. This is a signal to the programmer that an error might
occur if the precondtion is not met. In order to have a correct
and robust program, the programmer must deal with the possible error.
There are several approaches that the programmer can take.
One approach is to use an if statement to test whether the
precondition is satisfied. If not, the programmer can take some other
action such as printing an error message and terminating the program.
Another approach is to use a try statement to catch and
respond to the error. This is really just a cleaner way of accomplishing
the same thing as the first approach. The best approach, when it is
possible, is to ensure that the precondition is satisfied
as a result of what has already been done in the program.
For example, if the precondition is that x >= 0,
and the preceding statement is "x = Math.abs(y);", then
we know that the precondition is satisfied, since the absolute value
of any number is greater than or equal to zero.
Question 6:
Java has a predefined class called Throwable. What does this class represent?
Why does it exist?
Answer:
The class Throwable represents all possible objects that
can be thrown by a throw statement and caught
by a catch clause in a try...catch statement.
That is, the thrown object
must belong to the class Throwable or to one of its (many) subclasses
such as Exception and RuntimeException. The object
carries information about an exception from the point where the exception
occurs to the point where it is caught and handled.
Question 7:
Write a subroutine that prints out a 3N+1 sequence starting
from a given integer, N. The starting value should be a
parameter to the subroutine. If the parameter is less than or equal to
zero, throw an IllegalArgumentException. If the number in
the sequence becomes too large to be represented as a value of
type int, throw an ArithmeticException.
Answer:
The problem of large values in a 3N+1 sequence was discussed in
Section 1. In that section, it is pointed out
that the test "if (N > 2147483646/3)" can be used to test
whether the value of N has become too large. This test is
used in the following subroutine.
static void printThreeNSequence(int N) {
// Print the 3N+1 sequence starting from N. If N
// is not greater than 0 or if the value of N exceeds
// the maximum legal value for ints, than an
// exception will be thrown.
if (N < 1) {
throw new IllegalArgumentException(
"Starting value for 3N+1 sequence must be > 0.");
}
System.out.println("3N+1 sequence starting from " + N " is: ");
System.out.println(N);
while (N > 1) {
if (N % 2 == 0) { // N is even. Divide by 2.
N = N / 2;
}
else { // N is odd. Multiply by 3 and add 1.
if (N > 2147483646/3) {
throw new ArithmeticError(
"Value has exceeded the largest int.");
}
N = 3 * N + 1;
}
System.out.println(N);
}
}
(Note that it would be possible to declare that this routine can
throw exceptions by adding a "throws" clause to the heading:
static void printThreeNSequence(int N)
throws IllegalArgumentException, ArithmeticException {
However, this is not required since IllegalArgumentExceptions
and ArithmeticExceptions do not require mandatory exception handling.)
Question 8:
Some classes of exceptions require mandatory exception handling.
Explain what this means.
Answer:
Subclasses of the class Exception which are not
subclasses of RuntimeException require mandatory exception
handling. This has two consequences: First, if a subroutine can
throw such an exception, then it must declare this fact by
adding a throws clause to the subroutine heading.
Second, if a routine includes any code that can generate
such an exception, then the routine must deal with the
exception. It can do this by including the code in a try
statement that has a catch clause to handle the exception.
Or it can use a throws clause to declare that calling
the subroutine might throw the exception.
Question 9:
Consider a subroutine processData that has the header
static void processData() throws IOException
Write a try...catch statement that calls this
subroutine and prints an error message if an IOException
occurs.
Answer:
try {
processData();
}
catch (IOException e) {
System.out.println(
"An IOException occurred while precessing the data.");
}
Question 10:
Why should a subroutine throw an exception when it encounters
an error? Why not just terminate the program?
Answer:
Terminating the program is too drastic, and this tactic certainly doesn't
lead to robust programs! It's likely that the subroutine doesn't know
what to do with the error, but that doesn't mean that it should abort
the whole program. When the subroutine throws an exception, the
subroutine is terminated, but the program that called the subroutine
still has a chance to catch the exception and handle it. In effect,
the subroutine is saying "Alright, I'm giving up. Let's hope someone
else can deal with the problem."